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

コード決済における冪等性と整合性 / #merpay_techtalk

susho
December 18, 2019

コード決済における冪等性と整合性 / #merpay_techtalk

susho

December 18, 2019
Tweet

More Decks by susho

Other Decks in Technology

Transcript

  1. Tech Talk vol.2 Backend Engineer
    コード決済における冪等性と整合性

    View Slide

  2. About me
    ● susho (@susho0220)
    ● Backend Engineer
    ● Code Payment Team at Merpay
    ● Go歴4年くらい
    ● 2018年までYahooでオブジェクトストレージ Dragonの開発に従事

    View Slide

  3. メルペイのコード決済
    冪等性と整合性
    01
    02
    3
    Agenda

    View Slide

  4. メルペイのコード決済

    View Slide

  5. メルペイのコード決済
    ● CPM(Consumer-Presented Mode)
    ○ 一般社団法人キャッシュレス推進協議会が定める統一 QRコード・バーコード「JPQR」に準拠し
    たコード決済スキーム「 Smart Code(TM)」を採用。
    ● 静的MPM(Merchant-Presented Mode)
    ○ 国際ブランド6社からなる技術団体 EMVCoによって策定された共通規格である EMVを採用。
    ○ QRコードのEncode/Decodeには、自社で開発した OSSライブラリを利用。
    ■ mercari/go-emv-code
    ※ 「Smart Code」は、JCBの商標です。
    ※QRコードは(株)デンソーウェーブの登録商標です。
    ※EMV® is a registered trademark in the U.S. and
    other countries and an unregistered trademark elsewhere.
    The EMV trademark is owned by EMVCo, LLC.
    CPM MPM

    View Slide

  6. 冪等性と整合性

    View Slide

  7. 冪等性と整合性
    ● 決済サービスにとって、データの整合性が保たれていることはとても重要。
    ○ エラーになったはずなのにお客様の残高が引かれていた ...
    ○ エラーになったはずなのに加盟店様の売上口座からお金が引かれていた ...
    ■ サービス、会社の信頼性をなくしてしまう。

    View Slide

  8. しかし、マイクロサービスにおいて整合性を
    担保するのは難しい
    8

    View Slide

  9. モノリシックアーキテクチャの場合

    View Slide

  10. モノリシックアーキテクチャにおけるコード決済処理
    Monolithic Service
    1.request
    3.begin tx
    4.authorize & capture payment
    5. commit tx
    2.validate QR Code
    6.reply

    View Slide

  11. モノリシックアーキテクチャにおけるコード決済処理
    Monolithic Service
    1.request
    3.begin tx
    4.authorize & capture payment
    5. commit tx
    2.validate QR Code
    6.reply
    3-5のどれかでエラーになった
    としても、データベースの
    Atomic性の保証によって整合
    性は保たれる。

    View Slide

  12. マイクロサービスアーキテクチャの場合

    View Slide

  13. マイクロサービスアーキテクチャにおけるコード決済処理
    Code Payment Internal Payment
    1.request
    2.validate QR Code
    ● Pending: 初期状態
    ● Authorized: 残高の仮押さえ
    ● Captured: 決済確定
    Code Payment Internal Payment

    View Slide

  14. マイクロサービスアーキテクチャにおけるコード決済処理
    Code Payment Internal Payment
    1.request
    2.validate QR Code
    ● Pending: 初期状態
    ● Authorized: 残高の仮押さえ
    ● Captured: 決済確定
    Code Payment Internal Payment
    Pending
    3.begin tx
    4.mark state as pending
    5.commit tx

    View Slide

  15. マイクロサービスアーキテクチャにおけるコード決済処理
    Code Payment Internal Payment
    1.request
    2.validate QR Code
    ● Pending: 初期状態
    ● Authorized: 残高の仮押さえ
    ● Captured: 決済確定
    Code Payment Internal Payment
    Pending Pending
    3.begin tx
    4.mark state as pending
    5.commit tx
    6.authorize payment

    View Slide

  16. マイクロサービスアーキテクチャにおけるコード決済処理
    Code Payment Internal Payment
    1.request
    2.validate QR Code
    ● Pending: 初期状態
    ● Authorized: 残高の仮押さえ
    ● Captured: 決済確定
    Code Payment Internal Payment
    Pending Authorized
    3.begin tx
    4.mark state as pending
    5.commit tx
    6.authorize payment
    7. authorize payment

    View Slide

  17. マイクロサービスアーキテクチャにおけるコード決済処理
    Code Payment Internal Payment
    1.request
    2.validate QR Code
    ● Pending: 初期状態
    ● Authorized: 残高の仮押さえ
    ● Captured: 決済確定
    Code Payment Internal Payment
    Pending Authorized
    3.begin tx
    4.mark state as pending
    5.commit tx
    6.authorize payment
    7. authorize payment
    8.reply

    View Slide

  18. マイクロサービスアーキテクチャにおけるコード決済処理
    Code Payment Internal Payment
    1.request
    2.validate QR Code
    ● Pending: 初期状態
    ● Authorized: 残高の仮押さえ
    ● Captured: 決済確定
    Code Payment Internal Payment
    Authorized Authorized
    3.begin tx
    4.mark state as pending
    5.commit tx
    6.authorize payment
    7. authorize payment
    8.reply
    9.begin tx
    10.mark state as authorized
    11.commit tx

    View Slide

  19. マイクロサービスアーキテクチャにおけるコード決済処理
    Code Payment Internal Payment
    1.request
    2.validate QR Code
    ● Pending: 初期状態
    ● Authorized: 残高の仮押さえ
    ● Captured: 決済確定
    Code Payment Internal Payment
    Authorized Authorized
    3.begin tx
    4.mark state as pending
    5.commit tx
    6.authorize payment
    7. authorize payment
    8.reply
    9.begin tx
    10.mark state as authorized
    11.commit tx
    12.capture payment

    View Slide

  20. マイクロサービスアーキテクチャにおけるコード決済処理
    Code Payment Internal Payment
    1.request
    2.validate QR Code
    ● Pending: 初期状態
    ● Authorized: 残高の仮押さえ
    ● Captured: 決済確定
    Code Payment Internal Payment
    Authorized Captured
    3.begin tx
    4.mark state as pending
    5.commit tx
    6.authorize payment
    7. authorize payment
    8.reply
    9.begin tx
    10.mark state as authorized
    11.commit tx
    12.capture payment
    13. capture payment

    View Slide

  21. マイクロサービスアーキテクチャにおけるコード決済処理
    Code Payment Internal Payment
    1.request
    2.validate QR Code
    ● Pending: 初期状態
    ● Authorized: 残高の仮押さえ
    ● Captured: 決済確定
    Code Payment Internal Payment
    Authorized Captured
    3.begin tx
    4.mark state as pending
    5.commit tx
    6.authorize payment
    7. authorize payment
    8.reply
    9.begin tx
    10.mark state as authorized
    11.commit tx
    12.capture payment
    13. capture payment
    14.reply

    View Slide

  22. マイクロサービスアーキテクチャにおけるコード決済処理
    Code Payment Internal Payment
    1.request
    3.begin tx
    4.mark state as pending
    5.commit tx
    2.validate QR Code
    6.authorize payment
    7. authorize payment
    8.reply
    9.begin tx
    10.mark state as authorized
    11.commit tx
    18.reply
    12.capture payment
    13. capture payment
    14.reply
    15.begin tx
    16.mark state as captured
    17.commit tx
    ● Pending: 初期状態
    ● Authorized: 残高の仮押さえ
    ● Captured: 決済確定
    Code Payment Internal Payment
    Captured Captured

    View Slide

  23. エラーを考える
    23

    View Slide

  24. マイクロサービスアーキテクチャにおけるコード決済処理
    Code Payment Internal Payment
    1.request
    3.begin tx
    4.mark state as pending
    5.commit tx
    2.validate QR Code
    7. authorize payment
    9.begin tx
    10.mark state as authorized
    11.commit tx
    18.reply
    12.capture payment
    13. capture payment
    14.reply
    15.begin tx
    16.mark state as captured
    17.commit tx
    ● Pending: 初期状態
    ● Authorized: 残高の仮押さえ
    ● Captured: 決済確定
    ● Failed: 決済失敗
    Code Payment Internal Payment
    3-5でエラーになったとしても、
    データベースのAtomic性の保
    証によって整合性は保たれ
    る。
    6.authorize payment
    8.reply

    View Slide

  25. マイクロサービスアーキテクチャにおけるコード決済処理
    Code Payment Internal Payment
    1.request
    3.begin tx
    4.mark state as pending
    5.commit tx
    2.validate QR Code
    7. authorize payment
    9.begin tx
    10.mark state as authorized
    11.commit tx
    18.reply
    12.capture payment
    13. capture payment
    14.reply
    15.begin tx
    16.mark state as captured
    17.commit tx
    ● Pending: 初期状態
    ● Authorized: 残高の仮押さえ
    ● Captured: 決済確定
    ● Failed: 決済失敗
    Code Payment Internal Payment
    Pending
    Pending?
    Authorized? Failed?
    Internal Paymentの状態が不
    定なので不整合が発生してし
    まう。
    6.authorize payment
    8.reply

    View Slide

  26. マイクロサービスアーキテクチャにおけるコード決済処理
    Code Payment Internal Payment
    1.request
    3.begin tx
    4.mark state as pending
    5.commit tx
    2.validate QR Code
    7. authorize payment
    9.begin tx
    10.mark state as authorized
    11.commit tx
    18.reply
    12.capture payment
    13. capture payment
    14.reply
    15.begin tx
    16.mark state as captured
    17.commit tx
    ● Pending: 初期状態
    ● Authorized: 残高の仮押さえ
    ● Captured: 決済確定
    ● Failed: 決済失敗
    Code Payment Internal Payment
    Pending Authorized
    Code Paymentの状態と
    Internal Paymentの状態に不
    整合が発生してしまう。
    6.authorize payment
    8.reply

    View Slide

  27. マイクロサービスアーキテクチャにおけるコード決済処理
    Code Payment Internal Payment
    1.request
    3.begin tx
    4.mark state as pending
    5.commit tx
    2.validate QR Code
    7. authorize payment
    9.begin tx
    10.mark state as authorized
    11.commit tx
    18.reply
    12.capture payment
    13. capture payment
    14.reply
    15.begin tx
    16.mark state as captured
    17.commit tx
    ● Pending: 初期状態
    ● Authorized: 残高の仮押さえ
    ● Captured: 決済確定
    ● Failed: 決済失敗
    Code Payment Internal Payment
    Authorized
    Authorized?
    Captured?
    6.authorize payment
    8.reply
    Internal Paymentの状態が不
    定なので不整合が発生してし
    まう。

    View Slide

  28. マイクロサービスアーキテクチャにおけるコード決済処理
    Code Payment Internal Payment
    1.request
    3.begin tx
    4.mark state as pending
    5.commit tx
    2.validate QR Code
    7. authorize payment
    9.begin tx
    10.mark state as authorized
    11.commit tx
    18.reply
    12.capture payment
    13. capture payment
    14.reply
    15.begin tx
    16.mark state as captured
    17.commit tx
    ● Pending: 初期状態
    ● Authorized: 残高の仮押さえ
    ● Captured: 決済確定
    ● Failed: 決済失敗
    Code Payment Internal Payment
    Authorized Captured
    Code Paymentの状態と
    Internal Paymentの状態に不
    整合が発生してしまう。
    6.authorize payment
    8.reply

    View Slide

  29. ではどうするか
    29

    View Slide

  30. リトライすることによって不整合を修復する
    30

    View Slide

  31. しかし、リトライして多重決済になったりした
    らさらに事故...
    31

    View Slide

  32. リトライしても1回だけ実行される必要がある
    32

    View Slide

  33. 冪等性
    33

    View Slide

  34. 冪等性
    ● マイクロサービスが冪等性を持った APIを提供することで、Upper Layerのマイクロサービスは不整合
    が発生してもリトライによって多重に処理されることなく、安全に不整合を修復することができる。

    View Slide

  35. リトライで不整合が修復できるようになり整
    合性を担保できるようになった
    35

    View Slide

  36. もしリトライも失敗したら?
    36

    View Slide

  37. 不整合が発生したまま
    37

    View Slide

  38. ではどうするか
    38

    View Slide

  39. バッチによる定期的な不整合修復
    39

    View Slide

  40. バッチによる定期的な不整合修復
    ● リトライも失敗し、不整合が発生したままの決済トランザクションに対して、定期的に不整合を修復す
    る。
    ● 定期実行なので一定期間不整合が発生したままになるが、最終的に確実に整合性の保たれた状態
    にすることのできる必須なプロセス。

    View Slide

  41. バッチによる定期的な不整合修復
    Code Payment Internal Payment
    1.select pending state
    transactions
    Code Payment Internal Payment
    Pending
    Pending?
    Authorized? Failed?
    ● Pending: 初期状態
    ● Authorized: 残高の仮押さえ
    ● Failed: 決済失敗

    View Slide

  42. バッチによる定期的な不整合修復
    Code Payment Internal Payment
    1.select pending state
    transactions
    Code Payment Internal Payment
    Pending
    Pending?
    Authorized? Failed?
    ● Pending: 初期状態
    ● Authorized: 残高の仮押さえ
    ● Failed: 決済失敗
    2.get payment
    3.reply

    View Slide

  43. バッチによる定期的な不整合修復
    Code Payment Internal Payment
    1.select pending state
    transactions
    Code Payment Internal Payment
    Pending
    Pending?
    Authorized? Failed?
    ● Pending: 初期状態
    ● Authorized: 残高の仮押さえ
    ● Failed: 決済失敗
    2.get payment
    3.reply
    4.check payment state

    View Slide

  44. バッチによる定期的な不整合修復: Internal Payment State is Pending
    Code Payment Internal Payment
    1.select pending state
    transactions
    Code Payment Internal Payment
    Pending Pending
    ● Pending: 初期状態
    ● Authorized: 残高の仮押さえ
    ● Failed: 決済失敗
    2.get payment
    3.reply
    Internal Payment側のリトライ
    によってAuthorized or Failed
    に遷移するまで待つ。
    4.check payment state

    View Slide

  45. バッチによる定期的な不整合修復: Internal Payment State is Authorized
    Code Payment Internal Payment
    1.select pending state
    transactions
    Code Payment Internal Payment
    Pending Authorized
    ● Pending: 初期状態
    ● Authorized: 残高の仮押さえ
    2.get payment
    3.reply
    4.check payment state

    View Slide

  46. バッチによる定期的な不整合修復: Internal Payment State is Authorized
    Code Payment Internal Payment
    1.select pending state
    transactions
    Code Payment Internal Payment
    Pending Voided
    ● Pending: 初期状態
    ● Authorized: 残高の仮押さえ
    ● Voided: 仮押さえの取消
    2.get payment
    3.reply
    5.void payment
    6. void payment
    7.reply
    4.check payment state

    View Slide

  47. バッチによる定期的な不整合修復: Internal Payment State is Authorized
    Code Payment Internal Payment
    1.select pending state
    transactions
    Code Payment Internal Payment
    Voided Voided
    ● Pending: 初期状態
    ● Authorized: 残高の仮押さえ
    ● Voided: 仮押さえの取消
    2.get payment
    3.reply
    5.void payment
    6. void payment
    7.reply
    8.begin tx
    9.mark state as voided
    10.commit tx
    4.check payment state

    View Slide

  48. バッチによる定期的な不整合修復: Internal Payment State is Failed
    Code Payment Internal Payment
    1.select pending state
    transactions
    Code Payment Internal Payment
    Pending Failed
    ● Pending: 初期状態
    ● Failed: 決済失敗
    2.get payment
    3.reply
    4.check payment state

    View Slide

  49. バッチによる定期的な不整合修復: Internal Payment State is Failed
    Code Payment Internal Payment
    1.select pending state
    transactions
    Code Payment Internal Payment
    Failed Failed
    ● Pending: 初期状態
    ● Failed: 決済失敗
    2.get payment
    3.reply
    8.begin tx
    9.mark state as failed
    10.commit tx
    4.check payment state

    View Slide

  50. Authorizedに対するStateに対しても同様に
    実装する(結構辛い)
    50

    View Slide

  51. これで整合性が保たれるようになった
    51

    View Slide

  52. ここまでを踏まえてメルペイのコード決済
    アーキテクチャ
    52

    View Slide

  53. メルペイのコード決済アーキテクチャ: 同期処理
    Code Payment Transaction Internal Payment Pub/Sub
    1.request
    4.begin tx
    5.mark state as pending
    6.commit tx
    2.validate QR Code
    3.payment request
    7.authorize payment
    8. authorize payment
    9.publish authorized event
    10.reply
    11.begin tx
    12.mark state as authorized
    13.commit tx
    14.reply
    15.reply

    View Slide

  54. メルペイのコード決済アーキテクチャ: 非同期処理
    Transaction Internal Payment Pub/Sub
    3.check state whether
    authorized or not
    4.capture payment
    5. capture payment
    6.reply
    7.begin tx
    8.mark state as captured
    9.commit tx
    1.subscribe authorized event
    2.reply

    View Slide

  55. メルペイのコード決済アーキテクチャ: バッチ処理
    Transaction Internal Payment
    1.select pending state
    transactions
    2.get payment
    3.reply
    5.void payment
    6. void payment
    7.reply
    8.begin tx
    9.mark state as voided
    10.commit tx
    4.check payment state

    View Slide

  56. メルペイのコード決済アーキテクチャ
    ● 決済リクエストの同期処理では Authorizeまでを行い、Internal Payment ServiceによるAuthorizedイ
    ベントをSubscribeし、非同期でCaptureを行う。そして、同期処理で不整合が発生したままの決済を
    バッチ処理により修復する。
    ○ 同期処理でやる責務を最小限にし、それ以外の処理を成功するまでリトライ可能な非同期とし
    て実装することで、エラーハンドリングをシンプルにしている。
    ○ 不整合が発生しうる同期処理の状態遷移を Pending -> Authorizedにすることで、バッチ処理
    で修復する対象の状態を Pendingのみにしている。

    View Slide

  57. まとめ

    View Slide

  58. まとめ
    ● マイクロサービスアーキテクチャにおいて整合性を担保するのは難しい。
    ● 冪等性のあるAPIを提供することで、Upper Layerのマイクロサービスは多重決済されることなくリトラ
    イでき、不整合を修復できる。
    ● リトライでも不整合を修正できないパターンが存在するので、バッチによる修復プロセスも必ず実装
    する必要がある。

    View Slide

  59. View Slide