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

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

Eff335185b3defb426569def9f0a12a9?s=47 susho
December 18, 2019

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

Eff335185b3defb426569def9f0a12a9?s=128

susho

December 18, 2019
Tweet

Transcript

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

  2. About me • susho (@susho0220) • Backend Engineer • Code

    Payment Team at Merpay • Go歴4年くらい • 2018年までYahooでオブジェクトストレージ Dragonの開発に従事
  3. メルペイのコード決済 冪等性と整合性 01 02 3 Agenda

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

  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
  6. 冪等性と整合性

  7. 冪等性と整合性 • 決済サービスにとって、データの整合性が保たれていることはとても重要。 ◦ エラーになったはずなのにお客様の残高が引かれていた ... ◦ エラーになったはずなのに加盟店様の売上口座からお金が引かれていた ... ▪

    サービス、会社の信頼性をなくしてしまう。
  8. しかし、マイクロサービスにおいて整合性を 担保するのは難しい 8

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

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

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

    5. commit tx 2.validate QR Code 6.reply 3-5のどれかでエラーになった としても、データベースの Atomic性の保証によって整合 性は保たれる。
  12. マイクロサービスアーキテクチャの場合

  13. マイクロサービスアーキテクチャにおけるコード決済処理 Code Payment Internal Payment 1.request 2.validate QR Code •

    Pending: 初期状態 • Authorized: 残高の仮押さえ • Captured: 決済確定 Code Payment Internal Payment
  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
  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
  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
  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
  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
  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
  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
  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
  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
  23. エラーを考える 23

  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
  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
  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
  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の状態が不 定なので不整合が発生してし まう。
  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
  29. ではどうするか 29

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

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

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

  33. 冪等性 33

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

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

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

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

  38. ではどうするか 38

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

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

  41. バッチによる定期的な不整合修復 Code Payment Internal Payment 1.select pending state transactions Code

    Payment Internal Payment Pending Pending? Authorized? Failed? • Pending: 初期状態 • Authorized: 残高の仮押さえ • Failed: 決済失敗
  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
  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
  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
  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
  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
  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
  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
  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
  50. Authorizedに対するStateに対しても同様に 実装する(結構辛い) 50

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

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

  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
  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
  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
  56. メルペイのコード決済アーキテクチャ • 決済リクエストの同期処理では Authorizeまでを行い、Internal Payment ServiceによるAuthorizedイ ベントをSubscribeし、非同期でCaptureを行う。そして、同期処理で不整合が発生したままの決済を バッチ処理により修復する。 ◦ 同期処理でやる責務を最小限にし、それ以外の処理を成功するまでリトライ可能な非同期とし

    て実装することで、エラーハンドリングをシンプルにしている。 ◦ 不整合が発生しうる同期処理の状態遷移を Pending -> Authorizedにすることで、バッチ処理 で修復する対象の状態を Pendingのみにしている。
  57. まとめ

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

  59. None