Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

メルペイのコード決済

Slide 5

Slide 5 text

メルペイのコード決済 ● 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

Slide 6

Slide 6 text

冪等性と整合性

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

マイクロサービスアーキテクチャにおけるコード決済処理 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

Slide 15

Slide 15 text

マイクロサービスアーキテクチャにおけるコード決済処理 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

Slide 16

Slide 16 text

マイクロサービスアーキテクチャにおけるコード決済処理 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

Slide 17

Slide 17 text

マイクロサービスアーキテクチャにおけるコード決済処理 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

Slide 18

Slide 18 text

マイクロサービスアーキテクチャにおけるコード決済処理 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

Slide 19

Slide 19 text

マイクロサービスアーキテクチャにおけるコード決済処理 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

Slide 20

Slide 20 text

マイクロサービスアーキテクチャにおけるコード決済処理 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

Slide 21

Slide 21 text

マイクロサービスアーキテクチャにおけるコード決済処理 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

Slide 22

Slide 22 text

マイクロサービスアーキテクチャにおけるコード決済処理 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

Slide 23

Slide 23 text

エラーを考える 23

Slide 24

Slide 24 text

マイクロサービスアーキテクチャにおけるコード決済処理 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

Slide 25

Slide 25 text

マイクロサービスアーキテクチャにおけるコード決済処理 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

Slide 26

Slide 26 text

マイクロサービスアーキテクチャにおけるコード決済処理 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

Slide 27

Slide 27 text

マイクロサービスアーキテクチャにおけるコード決済処理 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の状態が不 定なので不整合が発生してし まう。

Slide 28

Slide 28 text

マイクロサービスアーキテクチャにおけるコード決済処理 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

Slide 29

Slide 29 text

ではどうするか 29

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

冪等性 33

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

不整合が発生したまま 37

Slide 38

Slide 38 text

ではどうするか 38

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

バッチによる定期的な不整合修復 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

Slide 43

Slide 43 text

バッチによる定期的な不整合修復 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

Slide 44

Slide 44 text

バッチによる定期的な不整合修復: 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

Slide 45

Slide 45 text

バッチによる定期的な不整合修復: 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

Slide 46

Slide 46 text

バッチによる定期的な不整合修復: 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

Slide 47

Slide 47 text

バッチによる定期的な不整合修復: 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

Slide 48

Slide 48 text

バッチによる定期的な不整合修復: 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

Slide 49

Slide 49 text

バッチによる定期的な不整合修復: 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

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

メルペイのコード決済アーキテクチャ: 同期処理 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

Slide 54

Slide 54 text

メルペイのコード決済アーキテクチャ: 非同期処理 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

Slide 55

Slide 55 text

メルペイのコード決済アーキテクチャ: バッチ処理 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

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

まとめ

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

No content