プレイブック

支払調整員建設 (Building A Payment Reconciliation Worker)

スイーパーによるドリフトの改善方法: PSP が成功している間、ローカル登録が期限切れになる可能性があります。古い FinalizePending を回復する方法。

分散型決済エンジン

一部 14 の 22

取得と完了の間のギャップを埋める一連の分散型支払いアーキテクチャ。

Distributed payment engine architecture diagram

前のセクションでは、リースメカニズムを使用してビジネスを安全に所有できる方法を見てきました。しかし、最も堅牢なリースであっても、1 つの事実を変えることはできません。PSP 側での支払いが実際に成功したときと同じように、PSP から最終的な応答を受け取る前にワーカーがタイムアウトしたり、プロセスがクラッシュしたり、リースの有効期限が切れてジョブが「期限切れ」とマークされたりすることがあります。

これが調整ワーカーの存在意義です。つまり、ローカル システムと PSP 自身の記録の間のずれを定期的にスキャンして修正するスイーパーです。```text Local kayıt: Payment #123 → Expired PSP kaydı: Payment #123 → Succeeded │ ▼ Mutabakat worker sürüklenmeyi tespit eder │ ▼ Local kayıt → Captured olarak düzeltilir


## 最初に説明した概念```text
📦 Reconciliation (Mutabakat)
İki bağımsız kaynağın (local sistem ve PSP) kayıtlarını karşılaştırıp farkı düzeltme süreci.

📦 Drift (Sürüklenme)
Local durumun PSP'nin gerçek kaydından farklılaşması; genellikle bir hata veya zaman aşımı sonucu.

📦 Sweeper
Belirli bir kritere uyan (örn. 'aged' veya 'expired') kayıtları periyodik olarak tarayan arka plan işi.

📦 FinalizePending
Ödemenin PSP tarafında sonuçlanmış olabileceği ama local sistemde henüz kesin bir duruma geçmediği ara statü.
```調整はリアルタイムの修正ではありません。それはセーフティネットです。メイン フロー (Webhook、同期応答) は、ほとんどの場合正しく機能します。コンセンサスは、その「ほとんどの場合」から取り残される少数派を排除します。

## ドリフトの本当の原因

ドリフトがランダムになることはほとんどありません。通常、ワーカーが PSP にリクエストを送信し、レスポンスが到着する前にプロセスがクラッシュするなど、特定の反復的なシナリオから発生します。ネットワークエラーにより応答は届きませんが、トランザクションは PSP 側で完了します。または、リース期間が PSP の応答時間より短く設定されており、ジョブが途中で「期限切れ」とマークされます。```text
Senaryo 1: Worker çöktü
  Request gönderildi → PSP işledi → Worker cevabı hiç okuyamadı

Senaryo 2: Ağ hatası
  Request gönderildi → PSP işledi → yanıt ağda kayboldu

Senaryo 3: Lease erken doldu
  Request gönderildi → PSP yavaş yanıt verdi → lease expired → job stuck watcher tarafından sıfırlandı → ama PSP zaten başarılı olmuştu
```3 つのシナリオすべてに共通するのは、**ローカル レジストリ**が不確実または誤ったステータスのままであるのに対し、**PSP 自体のレジストリ**はすでに本当の結果を知っているということです。

## スイーパーのクエリ: どのレコードをスキャンするか

調整ワーカーは、各レコードを PSP と常に比較するわけではありません。これはコストがかかり、不必要です。これは、「疑わしい」レコードのみを対象とします。つまり、一定の期間を過ぎた (古くなった) が、依然として中間ステータス (長期間にわたって `FinalizePending`、`Expired`、`Processing`) に留まるレコードです。```sql
SELECT id, provider_ref FROM payments
WHERE status IN ('FinalizePending', 'Expired')
  AND updated_at < now() - interval '10 minutes';
```「10 分」のしきい値は任意ではありません。これは、通常のフローが結果として得られるまでにかかる時間を示す SLA から得られます。このしきい値を下回るレコードはまだ「疑わしい」ものではなく、単に遅いだけである可能性があります。

## PSP のクエリと決定

各候補レコードについて、ワーカーは PSP のステータス クエリ API (利用可能な場合) または独自のアーカイブされた Webhook 履歴をチェックします。次の 3 つの結果が考えられます。```text
PSP: Succeeded  → local kaydı Captured'a taşı, semantik event yayınla
PSP: Failed     → local kaydı Failed'a taşı
PSP: Not Found / Unknown → local kaydı gerçekten sonuçsuz say, telafi akışına yönlendir
```ここで重要な点は、この遷移も冪等である必要があるということです。リコンシリエーション ワーカーが同じレコードを 2 回処理した場合でも、結果は変わってはなりません (たとえば、レコードがすでに `Captured` である場合、同じイベントを再度発行してはなりません)。

## 警告: スイーパーはサイレントに実行すべきではありません

コンセンサスワーカーが検出する各ドリフトは、可観測性シグナルを生成する必要があります。ドリフトの数が突然増加した場合、これは通常、メイン フロー (Webhook 処理、リース期間、ネットワーク) に問題があることを示しています。調整により、この問題は隠蔽されるのではなく、可視化されるはずです。

|メトリック |それは何を言っていますか |
| --- | --- |
|スキャンされた候補登録数 |メインストリームはどのように「クリーン」に実行されるのか |
|修正されたドリフトの数 |実際のデータの不一致量 |
|まだ解決されていないレコードの数 |手動レビューが必要なキュー |

## 混同されやすい区別```text
❌ Mutabakat gerçek zamanlı bir düzeltmedir
✓ Mutabakat periyodik bir güvenlik ağıdır, ana akışın yerini almaz

❌ Sürüklenme sayısı sıfır olmalı, aksi halde sistem bozuk
✓ Düşük ve stabil bir sürüklenme oranı normaldir; artan oran bir sinyaldir

❌ Her kayıt PSP ile karşılaştırılmalı
✓ Sadece 'aged' ve ara statüdeki kayıtlar hedeflenmeli
```## メインフローとの合意の役割

|サイズ |メインストリーム (Webhook/同期) |和解ワーカー |
| --- | --- | --- |
|スピード |秒 |分-時間 |
|範囲 |支払いごと |疑わしい/古い記録のみ |
|目的 |通常の方法 |セーフティネット |

## リコンシリエーションワーカーをインストールする際のチェックリスト

1. スイーパー クエリは、ビジネス SLA に基づいて「古い」しきい値を決定しますか、それとも乱数ですか?
2. PSP へのクエリは、PSP のレート制限と再試行ポリシーに従っていますか?
3. ドリフト補正は冪等ですか — 同じレコードが 2 回処理されても結果は変わりませんか?
4. 修正不可能なレコードは表示可能なキューに分類されますか (これも PSP では見つかりません)。
5. ドリフトの数はメ​​トリックとして監視されており、突然の増加に対してアラームが生成されますか?

## この記事で覚えておくべきこと

1. コンセンサスは主流を補完するものであり、代替するものではありません。メインストリームはほとんどの場合正しく機能し、スイーパーは残りの少数派をクリーンアップします。
2. スイーパーは、すべてのレコードではなく、年齢とステータスの基準を満たす疑わしいレコードをターゲットにします。
3. PSP のクエリ後の修正はべき等であり、その再試行規則に準拠する必要があります。
4. ドリフト数は可観測性信号です。静かにゼロに近づくと予想されており、突然の増加は警告です。

> コンセンサスワーカーは、システムがどれほど完璧であるかではなく、システムがどれほど正直であるかを示します。

次のセクションでは、このドリフトの最も迷惑な形式について考えます。顧客は PSP 側で請求されていますが、システムには順序がありません。また、これを安全に解決するにはどうすればよいでしょうか?

FAQ

よくある質問

和解とは何ですか?

2 つの独立したソース (ローカル システムと PSP) からの録画を比較し、差異を修正するプロセス。

ドリフトとは何ですか?

ローカル状態は PSP の実際の記録とは異なります。通常はエラーまたはタイムアウトの結果として発生します。

「和解はリアルタイム修正」って本当ですか?

コンセンサスは定期的なセーフティネットであり、メインフローに代わるものではありません

このセクションでは何を修正しますか?

これが調整ワーカーの存在意義です。つまり、ローカル システムと PSP 自身の記録の間のずれを定期的にスキャンして修正するスイーパーです。コンセンサスは主流を補完するものであり、代替するものではありません。メインストリームはほとんどの場合正しく機能し、スイーパーは残りの少数派をクリーンアップします。前のセクションでは、リースメカニズムを使用してビジネスを安全に所有できる方法を見てきました。しかし、最も堅牢なリースであっても、1 つの事実を変えることはできません。PSP 側での支払いが実際に成功したときと同じように、PSP から最終的な応答を受け取る前にワーカーがタイムアウトしたり、プロセスがクラッシュしたり、リースの有効期限が切れてジョブが「期限切れ」とマークされたりすることがあります。

学んだエンジニアリング原則

  • コンセンサスはメインフローを補完するものであり、代替するものではありません。
  • スイーパーは、すべてのレコードではなく、古いレコードや疑わしいレコードをターゲットとします。
  • ドリフト数は信号です。静かにゼロに近づいた場合、突然の増加には警告が必要です。

続きを読む

続きを読む

シリーズの次のシリーズ

エッセイ

有料だが注文なし: 改善

インシデント対応ガイド: 顧客は請求したが注文はされなかった。多目的のバスケットの乱雑さ。重複除去を慎重にクリーニングします。

シリーズの次のシリーズ

同じシリーズ

Paylaş