Upgrade to Pro — share decks privately, control downloads, hide ads and more …

決済システムの信頼性を支える技術と運用の実践

Avatar for ykagano ykagano
November 08, 2025

 決済システムの信頼性を支える技術と運用の実践

2025/11/8 PHPカンファレンス福岡2025 発表資料

Avatar for ykagano

ykagano

November 08, 2025
Tweet

More Decks by ykagano

Other Decks in Technology

Transcript

  1. © 2012-2025 BASE, Inc. 2 氏名:加賀野 祐(ykagano) 所属:BASE株式会社 Cartチーム 業務:バックエンド エンジニア

    趣味:お酒、旅行、キャンプ 以下の決済サービスの開発を経験してきました - 2009年〜:NET CASH - 2012年〜:WebMoney - 2017年〜:Yahoo!ウォレット PayPay、PayPayカード - 2024年〜:BASE ykagano 自己紹介
  2. © 2012-2025 BASE, Inc. ネットショップ作成サービス「BASE」 3 ショップ開設数 (個人・法人・行政を含む) 240万ショップ以上 BASEかんたん決済利用料

    3.6%+40円 サービス利用料 3% コンセプト:「誰でも簡単に使えるネットショップ作成サービス」 初期費用・月額費用 0円 ショップオーナーのサポート機能が充実! 個人でも決済機能をかんたん導入。 審査もスピーディー! クレジットカード 銀行振込 コンビニ決済・Pay-easy 後払い (BASE Apps) キャリア決済 5年以内にネットショップを開設する際に利用したカート型ネットショップ開設サービス 調査委託先:マクロミル( 2025年2月実施)
  3. © 2012-2025 BASE, Inc. いきなり夢を壊しますが 6 決済ドメインはきついです! • 障害時の影響が大きい •

    夜間リリース普通にある • アラートで深夜に電話が鳴る • 開発時にも考慮することが多数 • テストにも多大なコストがかかる
  4. © 2012-2025 BASE, Inc. 他にも 8 取引に直接影響するため、考えることも多く、やりがいも大きいです • システム稼働率をどうやって100%に近づけるか •

    ユーザーの決済体験をいかに向上させるか • 増え続ける決済リクエストを捌くには • アラートを取りこぼさないようにするには
  5. © 2012-2025 BASE, Inc. カード決済(オーソリ)と突合バッチ 10 今回はカード決済(オーソリ)と突合バッチをイメージいただいた上で、 各設計についての話をしようと思います 1円オー ソリ

    カード登録 カード決済 バッチ処理 認証 不正 対策 流量 制限 オーソリ オーソリ 取消 トークン 化 突合 集計 再取消 クリアリ ング キャプ チャ
  6. © 2012-2025 BASE, Inc. 本当だった 13 正規化とパフォーマンスはトレードオフの関係 検 索 パ

    フ ォ I マ ン ス データ整合性 ミック:著(2012) 達人に学ぶDB設計 図5-2 データ整合性とパフォーマンスのトレードオフ関係 より引用 第1正規形 第2正規形 第3正規形 高 低 高 低
  7. © 2012-2025 BASE, Inc. クリス・デイトの言葉を紹介します 14 「非正規化」はあくまでも最後の手段であるという姿勢で のぞむ、というものだ。要するに、十分に正規化された 設計をあきらめてよいのは、パフォーマンスを向上させる ためのその他すべての戦略が要件を満たさない場合だけ

    である。 DBでパフォーマンスを向上しないと要件を満たせない場合だけは 非正規化するのもやむを得ないと捉えています ミック:著(2012) 達人に学ぶDB設計 第5章 論理設計とパフォーマンス より引用
  8. © 2012-2025 BASE, Inc. 正規化/非正規化のメリット・デメリット 15 では決済システムにとって非正規化しないといけない理由とは何か、 テーブルの正規化と非正規化のメリット・デメリットをあらためて表にまとめてみました 観点 正規化

    非正規化 メリット デメリット メリット デメリット SELECT 整合性が高く重複が少ない JOINが多く遅くなる JOIN不要で高速 冗長で整合性崩れやすい UPDATE 一箇所更新で済む 更新が複雑になりやすい ほぼなし 複数箇所の更新が必要 INSERT 重複を避け効率的 挿入処理が複雑 書き込み回数が少ない データが肥大化しやすい
  9. © 2012-2025 BASE, Inc. 正規化/非正規化のメリット・デメリット 16 では決済システムにとって非正規化しないといけない理由とは何か、 テーブルの正規化と非正規化のメリット・デメリットをあらためて表にまとめてみました 決済システムでは、非正規化のメリットとして、INSERTの書き込み回数が少ないというのが 大きなメリットと考えています

    決済システムには大量の決済負荷があり、いかに決済を完了させるまでの処理を短くするかが重要で INSERTの回数を減らすための設計が必要となります 観点 正規化 非正規化 メリット デメリット メリット デメリット SELECT 整合性が高く重複が少ない JOINが多く遅くなる JOIN不要で高速 冗長で整合性崩れやすい UPDATE 一箇所更新で済む 更新が複雑になりやすい ほぼなし 複数箇所の更新が必要 INSERT 重複を避け効率的 挿入処理が複雑 書き込み回数が少ない データが肥大化しやすい
  10. © 2012-2025 BASE, Inc. 決済処理に必要なDBの最小構成例 18 • 決済リクエストテーブル • 決済トランザクションテーブル

    • 決済結果テーブル この3つのテーブルへのINSERTのみで決済処理を考えてみます 決済リクエスト REQUEST_ID REQUEST_DATE AMOUNT … CREATE_DATE UPDATE_DATE 決済トランザクション TRANSACTION_ID TRANSACTION_DATE AMOUNT … CREATE_DATE UPDATE_DATE 決済結果 REQUEST_ID PAYMENT_STATUS AMOUNT … CREATE_DATE UPDATE_DATE
  11. © 2012-2025 BASE, Inc. DB含めた決済APIの最小構成例 19 こうしてINSERT処理だけにすることでパフォーマンスを向上させられます 決済リクエスト REQUEST_ID …

    決済トランザクション TRANSACTION_ID … 決済結果 REQUEST_ID … 決済リクエストが処理済みか判定 なければ決済リクエストテーブルに書き込む 決済結果テーブルにあれば冪等の結果を応答 情報収集後、決済トランザクションテーブルに書き込む 決済トランザクションログに書き込む( DBダウン用) 外部に決済をリクエスト 決済の成否を決済結果テーブルに書き込む 決済リクエストテーブルにあれば一意制約違反で応答 決済API リクエスト 決済失敗時は決済キャンセルのPub/Subに登録 書き込み失敗時は決済キャンセルのPub/Subに登録
  12. © 2012-2025 BASE, Inc. BASEではどうやっているのか 20 BASEでは決済手段ごとに テーブルを分けています また通信トランザクションは追記型で テーブルに記録してます

    この辺りはどの決済システムも 同じようにしているものと思います 個人でも決済機能をかんたん導入。 審査もスピーディー! クレジットカード 銀行振込 コンビニ決済・Pay-easy 後払い キャリア決済 PayPal Amazon Pay
  13. © 2012-2025 BASE, Inc. 負荷分散キャンペーンへ 24 そのため、最近はユーザーの購買意欲を分散させつつ売上を最大化するために キャンペーンを長期間(1週間以上)続けたり、 キャンペーンの終了時刻を深夜(AM2:00等)にするようになったものと思います ▪アリババの独身の日は数週間

    ロイター:中国「独身の日」商戦終了、買い物客が増加 総売上高は推計26.6%増 https://jp.reuters.com/markets/japan/funds/ED7YUAMZVJIJ7BNQJEPFQQQMFM-2024-11-12/ ▪超PayPay祭も数週間(AM2:00終了) コマースピック:Yahoo!ショッピング「超PayPay祭」で取扱高前年比112%を達成、2025年最高の売上記録 https://www.commercepick.com/archives/71111
  14. © 2012-2025 BASE, Inc. カード決済の負荷テスト 27 通常、決済代行を通して、カード会社に承認を取りに行くと遅くなります 決済ネットワークも通るため、数秒かかります アクワイアラー 決済代行

    加盟店 CAFIS カード会社 CAFIS 加盟店 アクワイアラー カード会社 カード加盟店を管理 しかし、カード会社のシステムに直接繋ぎ込みをして決済すれば早くなるため、 大手企業はグループにカード会社を作ってオンアス取引(社内取引)をしています 決済ネットワーク
  15. © 2012-2025 BASE, Inc. 負荷テストの対象システム 28 クレジットカード決済で負荷テストをする際、 決済システムからアクワイアラーを通してカード会社の3者間を通す 負荷テストを実施していました 事業体制にもよるものと思いますが、

    自身の経験としてはこちらの構成で負荷テストを実施していました この構成だと基本的にレスポンスは1秒以内に応答されます 決済システム カード会社 アクワイアラー
  16. © 2012-2025 BASE, Inc. 改善サイクルを回す 32 大規模な決済システムを担当していた頃は、 3ヶ月に1回程度負荷テストをしていました ボトルネックが見つかると以下のサイクルを回してました •

    修正方針を立てる • スケジュールを作る • 修正・検証 • 負荷テストの再実施 あれ、最近負荷テストの対応しかしてない・・・なんて時もありました
  17. © 2012-2025 BASE, Inc. 負荷テストの実施 33 負荷テストを実施する際は、 どこまでの負荷にシステムが耐えられるか確認するために、 徐々に負荷を上げてテストします 先ほどの例ですと、

    200rps、250rps、300rps、350rps と 徐々に上げていきますが、既に250tpsまでは問題ないことが分かっている場合は、 300rpsから始めたりします シナリオ 1 2 3 4 5(目標) 6 7 rps 200rps 250rps 300rps 350rps 400rps 450rps 500rps 実行時間 5分 5分 5分 5分 5分 5分 5分
  18. © 2012-2025 BASE, Inc. 時系列の文字列 35 例えば2024年から2025年へ変わる1秒前にデータの書き込みが発生したとします 「20241231235959ASDFGH」 「20241231235959ZXCVBN」 という2つの文字列を主キーにINSERTしようとした場合、

    先頭からの文字列の大半が同一です そのため、Bツリー索引により同じリーフブロックが更新されてしまい スプリット待ちにより、DBの待機イベントが発生していました
  19. © 2012-2025 BASE, Inc. スプリット(リーフブロックの再編成) 37 階数t=2(キーの最大数=3)の場合 
 • ノード[5,6,7]

    に 8 を挿入するとキーが4つに溢れてしまう 
 • そのため、中央値 7 を親に昇格させてノードを分割 
 • 左の子が[5, 6]、右の子が[8]になり、部分木の順序性(左 < 親 < 右)が保たれる 再編成
  20. © 2012-2025 BASE, Inc. 対策 38 文字列全体を分散させることが必要だったため、 主キーに入る値をハッシュ化した値に変更しました ハッシュ化前:20241231235959ASDFGH ハッシュ化後:6F5C6F7F3408F9FC4F91845E6C686B8ED8D61F51082B012F3C8989FD53D5F648

    そしてハッシュ化前の値は新しく追加したカラムへ入れることにしました 下記テーブルのイメージです カラム名 データ型 備考 REQUEST_ID varchar(255) リクエストID(ハッシュ化後) … … ORIGINAL_REQUEST_ID varchar(255) リクエストID(ハッシュ化前)
  21. © 2012-2025 BASE, Inc. 突合の流れ 44 カード決済の突合バッチは、下記⑤のタイミングで起動する単体バッチです 注文システム 決済システム ①前日に大量の決済オーソリ

    ③決済ファイルのURLをAPIにリクエスト ④決済ファイルを取得 ⑤同じ決済があるかチェック ②翌日、決済ファイルを作成 突合バッチ
  22. © 2012-2025 BASE, Inc. 突合バッチでのチェック 45 システム間の結果が間違ってはならないので、複数の観点でチェックを行います 1件あたりでは、同一リクエストか、同一金額か、ステータスは一致しているか 全件あたりでは、合計件数や合計金額が一致しているか確認します REQUEST_ID

    AMOUNT STATUS AAA… 1000 auth BBB… 2000 auth CCC… 3000 auth … … 合計件数 合計金額 1000000 2,000,000,000 行の一致 合計の一致 REQUEST_ID AMOUNT STATUS AAA… 1000 auth BBB… 2000 auth CCC… 3000 auth 合計件数 合計金額 1000000 2,000,000,000
  23. © 2012-2025 BASE, Inc. 突合バッチの機能テスト 46 CIで動作するバッチの機能テストではデータファイルに想定される データパターンを可能な限り用意します CI用のDBにデータを一時的に流し込み、そのデータをバッチに読み込ませて 出力結果が一致することを確認します

    出力結果 ・合計件数 ・合計金額 決済データ 入力 ファイル 期待値 ・合計件数 ・合計金額 バッチの 突合処理 決済データを DBに取り込む DB バッチの突合処理を実行する 実行結果を確認する バッチのIN/OUTの結果を 常に担保する テストシナリオ 一致を確認
  24. © 2012-2025 BASE, Inc. まとめ 53 • データベース設計 ◦ パフォーマンスを向上させるためにDBの非正規化も選択肢

    ◦ 決済は追記型で処理することも選択肢 • 負荷テスト ◦ キャパシティプランニングを元に、性能要求を満たすための改善サイクルを回す ◦ INSERTが多いテーブルの主キーに時系列な文字列(前方一致)は使わない • バッチ設計 ◦ バッチの機能テストではIN/OUTの結果を常に担保する ◦ データが増加しても、変わらず処理ができるように長期的な視点での設計が必要