2024.12.19
システムの穴を運用でカバーしようとしてミス多発… バグが大量発生、決算が合わない状態から業務効率化を実現するまで
オンライン即売会を支えた技術(全1記事)
リンクをコピー
記事をブックマーク
金川祐太郎氏(以下、金川):「オンライン即売会を支えた技術」。BOOTH部の金川がお話します。よろしくお願いします。
「BOOTH」では、突然の決済スパイクに頭を抱えていました。決済スパイクは、例えば有名なクリエイターの期間限定販売や、「YouTube」などVTuberの配信中に商品が公開された時、あとは最近行われるエアコミケといったオンライン即売会などで発生します。
決済スパイクが起きる時、BOOTHでは同じ商品に注文が集中します。この時に何に困るかというと、これはBOOTHで以前行われていた処理なのですが、同じトランザクションの中で在庫処理と決済処理を同時に行っています。まず商品で悲観的ロックを取り、在庫の減算を行い、注文の確定を行ってから決済確定APIを呼び出します。この時、同じ商品で注文が殺到してしまうと、注文を1つずつしか捌けないため、時間のかかる処理が行われていた場合、トランザクションが詰まってしまいます。
実際にこれは同じ商品に注文が殺到したケースで、ピクシブ株式会社では「DataDog」というツールを使って処理のかかっている時間を見られるのですが、この決済処理には約13秒ほどの時間がかかっていて、そのほとんどが在庫ロック待ちで使われていました。
そこでスパイクを捌くためのアプローチとして、3つの方法を考えました。まず1つ目が、在庫1個ごとにレコードを用意する方法。2つ目が、決済されるごとに「Sidekiq」にジョブを積んで非同期で処理を行う方法。3つ目が、トランザクションを分割するという方法です。
まず、在庫1個ごとにレコードを用意する方法です。これは最初に考えた方法で、「在庫 ロック」などで検索を行うと出てくる事例です。在庫ごとにレコードを作って、個別にロックを取ればいいという方法なのですが、BOOTHの在庫数をsumで取ってみたところ数億になったので、さすがにこれは現実的ではないと断念しました。
2つ目は、決済されたらSidekiqにジョブを積んで非同期で決済を行う方法です。決済が完了したらメールやポーリングなどを使ってユーザーに通知します。しかしこれを行うと、決済を確定するボタンを押してからその結果を知るまで、その決済の注文の状態がわからなくなる時間が増えてしまいます。
例えば決済に2秒かかるとして、一気に1,000個注文が入った場合、注文が1個ずつしか処理されないので、1,000個注文目の人は30分近く結果を待たされてしまいます。なので、これも断念しました。
採用した方法は、トランザクションの分割です。在庫の減算と決済の2つにトランザクションを分割します。在庫の減算は悲観的ロックを取りながら在庫を減らすというトランザクションで、これは数百ミリ秒ぐらいの処理時間です。もう1つが悲観的ロックを取らずに決済確定APIを叩くトランザクションです。これはロックを取らないので並列に実行できますが、約2秒ほど長い時間がかかります。
この2つのトランザクションに分けることで、体験を変えずに決済処理を並列で行えるようになりました。
この処理の詳細な流れを説明します。1つ目が在庫管理トランザクションです。2つ目が決済確定トランザクションです。1つ目の在庫管理トランザクションでは、商品を管理している棚をイメージしてください。棚から商品を取り出せるのは1人ずつです。その棚からレジの横に商品を確保しておくというイメージで、在庫確保テーブルに商品情報を挿入します。
そのあと在庫減算を行って、いったんその処理をコミットします。次に在庫確保レコードを削除して、注文確定状態にして、決済確定APIを呼び出します。ここは、レジの横にどけておいた商品を実際にレジで決済を行うというイメージです。なので、ここは悲観的ロックが必要ありません。
これは正常系の流れです。ここでエラーが起きた時の流れをちょっと考えてみましょう。マイクロサービスパターンのSagaパターンの中に補償トランザクションがあるのですが、それと同じイメージで、決済トランザクションで失敗した時に、在庫トランザクションはすでにコミットされているので、それを手動で取り消す必要があります。
例えば決済トランザクションの最後で、決済APIが失敗したというケースを考えます。この場合、決算トランザクションは自動でロールバックされるのですが、在庫管理トランザクションはロールバックできないので、在庫管理トランザクションで行った処理の逆順の処理をすればOKです。なので、まず在庫で悲観的ロックを取ってから商品情報を削除して、在庫を加算します。
ここでもう1つ考えないといけないのは、この補償トランザクションで失敗した時のケースです。例えばRDBの障害などが考えられます。この場合、補償トランザクションが失敗してしまうので、べき等な操作にしておいて再実行可能にしておく必要があります。今回の場合、バッチで長時間残っている在庫を確保した商品については、もう一度同じ補償トランザクションを再実行するという方法で解決しています。
改善を入れる前は、最大分間注文数がだいたい400件ぐらいしか捌けなかったのですが、この改善によって分間2,000注文を捌けるようになりました。めでたしめでたしですね。
これは後日談なのですが、ある日突然BOOTH全体が重くなりました。注文自体は捌けていたのですが、CPUが100パーセント張り付くという障害が起きてしまいました。slimのレンダリングに時間がかかっていたことが原因でした。今まで注文が捌ききれていなかったので、ボトルネックになるところが移動したという感じです。
ここの処理を追いかけたところ、slimが遅いことがわかりました。ユーザーの設定によって表示する内容が変わるため部分的なキャッシュも難しく、今後はフロントで組み立てる方向に寄せていく予定です。
最後にまとめです。悲観的ロックを取るトランザクションの中で、時間のかかる処理をしないのが最善です。ただ、どうしても必要な場合があるので、その場合はトランザクションの分割を検討します。最後にDOMの組み立てはけっこう大変なので、今後はフロントにDOMの組み立ての処理を寄せていくのがよいかなと思っています。以上です。ありがとうございました。
司会者:金川さんの発表は以上です。ではこれから質疑応答に入っていきたいと思います。「決済と在庫の最終的な結果整合性はどうやって確認できているんですか?」とという質問です。
金川:整合性は、問い合わせベースがあるのと、もう1つ、スライドの中でも語っていたんですが、きちんとロールバックが行われているかを定期的なジョブで確認しているので、そこで「おかしいぞ?」となったらアラートが上がるようにしています。
司会者:ありがとうございます。次「使っているRDBは何ですか?」という質問がありました。
金川:弊社は基本的にMySQLを使っています。バージョンとしては5.6だったかな?
司会者:ありがとうございます。ではこちらの質問もお願いします。「整合性が取れなくなってしまう頻度はどの程度なのでしょうか?」
金川:整合性を2つの方法で確認していると話したと思うんですが、まず問い合わせベースはほぼ来たことがないです。トランザクションが失敗したケースも今まで1回起きたぐらいで、あとは自然に解消されています。
司会者:ありがとうございます。「ダミーのカードデータで大量に購入して、決済確定が失敗しまくった場合、在庫をゼロにできてしまう攻撃ができそうな気がしたのですが、在庫側のロールバックはどの程度の時間で完了するのでしょうか?」という質問が来ています。
金川:まず失敗した段階で、レスポンスを返すのと同じリクエストの中で一緒にロールバックをやっちゃおうという方針にしていて、そこで失敗しなかったケアとして、非同期でもう一度補償トランザクションを走らせるというかたちになっているので、その攻撃はたぶん成り立たないはずです。
司会者:なるほど。そのリクエスト中で失敗する確率はそこまで高くないだろうという感じですね。
金川:そうですね。DBとの接続が切れない限りという感じですね(笑)。
司会者:どうもありがとうございます。ここで金川さんの発表は終わりにしたいと思います。
2024.12.20
日本の約10倍がん患者が殺到し、病院はキャパオーバー ジャパンハートが描く医療の未来と、カンボジアに新病院を作る理由
2024.12.19
12万通りの「資格の組み合わせ」の中で厳選された60の項目 532の資格を持つ林雄次氏の新刊『資格のかけ算』の見所
2024.12.16
32歳で成績最下位から1年でトップ営業になれた理由 売るテクニックよりも大事な「あり方」
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
PR | 2024.12.20
モンスター化したExcelが、ある日突然崩壊 昭和のガス工事会社を生まれ変わらせた、起死回生のノーコード活用術
2024.12.12
会議で発言しやすくなる「心理的安全性」を高めるには ファシリテーションがうまい人の3つの条件
2024.12.18
「社長以外みんな儲かる給与設計」にした理由 経営者たちが語る、優秀な人材集め・会社を発展させるためのヒント
2024.12.17
面接で「後輩を指導できなさそう」と思われる人の伝え方 歳を重ねるほど重視される経験の「ノウハウ化」
2024.12.13
ファシリテーターは「しゃべらないほうがいい」理由 入山章栄氏が語る、心理的安全性の高い場を作るポイント
2024.12.10
メールのラリー回数でわかる「評価されない人」の特徴 職場での評価を下げる行動5選
Climbers Startup JAPAN EXPO 2024 - 秋 -
2024.11.20 - 2024.11.21
『主体的なキャリア形成』を考える~資格のかけ算について〜
2024.12.07 - 2024.12.07
Startup CTO of the year 2024
2024.11.19 - 2024.11.19
社員の力を引き出す経営戦略〜ひとり一人が自ら成長する組織づくり〜
2024.11.20 - 2024.11.20
「確率思考」で未来を見通す 事業を成功に導く意思決定 ~エビデンス・ベースド・マーケティング思考の調査分析で事業に有効な予測手法とは~
2024.11.05 - 2024.11.05