学習・技術検証用デモ — 本システムは実際の銀行サービスではありません。

公開情報をもとに構築した教育目的のシステムです。実在する個人情報・口座情報・機密情報・認証情報等を入力しないでください。

ミニ銀行ACADEMY SYSTEM LEARNING
教材メニュー
学習進捗0 / 134
あと134項目
ADVANCED · 発展COURSE 09 · BANKING ENGINEERING

銀行エンジニアリング 04:冪等性・残高再構築・整合性検査

同じ依頼が2回届いても1回分しか記帳しない。台帳から残高をいつでも作り直せる。ずれを自動で見つける。この3つが、障害時にも説明できる銀行システムの土台です。

04 / 55
BANKING ENGINEERING · 銀行エンジニアリング

v8以降に実装した台帳・記帳エンジンなどを実際に動かし、正常時と異常時の両方から銀行システムの構造を学ぶ。

Prerequisite: BANKING SYSTEM

LEARNING GOALS

このページで学ぶこと

  • Idempotency Key と request fingerprint
  • 時点を指定した残高再構築
  • Posting整合性検査が見るもの
  • 「DB更新直後にAPI応答が失敗した」ときの考え方

PLAIN LANGUAGE

まず、ここだけつかむ

1

同じ Idempotency Key の依頼は、内容が同じなら同じ結果を返し、違えば拒否します。

2

通信エラー後は同じキーで再送すれば、記帳済みかどうかに関係なく1件だけになります。

3

仕訳から残高をいつでも再構築でき、整合性検査がずれを見つけて記録します。

DIFFICULT PARTS, STEP BY STEP

難しいポイントを、順番にほどく

専門用語を覚えることより、「なぜ必要か」「このシステムのどこで使うか」を理解することが目標です。

01

Idempotency Key

やさしく言うと

1つの依頼を識別する番号です。

なぜ必要?

再送を安全にするためです。

Minibankでは

(発生元, イベント種別, キー)の一意制約と fingerprint 照合(PE009)。

02

Balance Reconstruction

やさしく言うと

記録から残高を計算し直すことです。

なぜ必要?

キャッシュが正しいか確かめ、過去時点の残高を説明するためです。

Minibankでは

posting.recompute_balances(時点)。

03

Integrity Check

やさしく言うと

記録全体の不変条件を後から検査することです。

なぜ必要?

処理中の防御をすり抜けたずれを見つけるためです。

Minibankでは

posting.run_integrity()。check_type は posting。

Level 1 基礎:同じ依頼を2回受け取ったら

通信が不安定だと、利用者の画面は「失敗した」と表示していても、銀行側では処理が終わっていることがあります。利用者がもう一度ボタンを押しても二重に記帳しないよう、依頼ごとに一意な番号(Idempotency Key)を付けて、同じ番号の依頼は同じ結果を返します。この性質を冪等性(Idempotency)と呼びます。

Level 3 システム:MiniBankでの実装(正常時)

仕組み実装
一意性posting.business_events の(発生元, イベント種別, Idempotency Key)に一意制約
内容の一致確認イベント種別・金額・文脈から作る request fingerprint が同じなら既存イベントを返し、違えば PE009
同時に届いた重複posting.find_idempotent() が同じキーの処理を advisory lock で直列化してから確認する
画面からの再送管理画面の操作フォームは送信ごとに Idempotency-Key を作り、通信エラー後の再送では同じキーを使う

異常時:DB更新直後にAPI応答が失敗した

段階内容
症状管理者の画面に「通信エラー」と表示されたが、記帳されたかどうか分からない
調査同じ Idempotency Key で再送する。フォームは通信エラー時にキーを保持している
考えられる原因①DBに届く前に失敗 ②DBで記帳が完了した後、応答だけが失われた
真因の見分け方再送で①なら新しく記帳され、②なら既存のイベントがそのまま返る。どちらでも記帳は1件だけ
対応結果が返るまで同じキーで再送する。新しいキーで送り直すと別の依頼になり二重記帳の原因になる
再発防止キーは画面操作の開始時に1つ作り、成功または確定的な失敗(4xx)まで使い続ける

Level 3 システム:残高の再構築と整合性検査

  • posting.recompute_balances(時点):仕訳明細だけから全勘定の残高を計算し直し、顧客口座は cached_balance との差額も返す。時点を指定すると、その時刻までの仕訳だけで計算する
  • posting.run_integrity():全体の借方=貸方、仕訳ごとの借方=貸方、cached残高と仕訳残高、イベント⇔仕訳⇔ルールの対応、イベント金額と仕訳合計、イベントのない仕訳、取消仕訳が元仕訳の正確な反転か、を検査する
  • 検査結果は v7 と同じ reconciliation.integrity_runs / integrity_issues に check_type = 'posting' として保存され、v7 の整合性チェック画面にも表示される

異常時:検査が不一致を見つけた

DBテストでは、テスト用DBに限りトリガーを外して残高キャッシュを7円ずらし、借方だけの明細を1行差し込みます。検査は BALANCE_MISMATCH・JOURNAL_NOT_BALANCED・LEDGER_TOTAL_IMBALANCE を検出し、差し込みを元に戻すと再び0件になることを確認しています。

Level 4 アーキテクチャ:Exactly-once は作らず、At-least-once+冪等で近づける

ネットワーク越しに「必ず1回だけ届く」ことは保証できません。現実的な設計は「少なくとも1回は届ける(再送する)」と「受け取る側で重複を無害にする(冪等)」の組み合わせです。MiniBankは、キーの一意制約・内容の照合・直列化の3点で、記帳が1回分だけになる状態を作っています。

さらに、記帳の正しさは処理中の検査だけに頼らず、後から台帳全体を検査して確かめます。処理時の防御と事後の照合を分けることで、想定外の経路で生じたずれも見つけられます。

どこを確認すればよいか

  • 管理画面「Ledger・Posting」→ Posting整合性チェック・残高差異
  • 管理画面「整合性チェック」→ check_type が posting の実行履歴
  • scripts/banking/v8-posting.test.mjs の各テスト

CHECK YOUR UNDERSTANDING

3問で理解チェック

答えを頭の中で考えてから、各項目を開いて確認してください。

Q1通信エラーの後、新しいキーで送り直すと何が起こりえますか?
答え

前の依頼が実は成功していた場合、二重記帳になります。

Q2同時に同じキーで6回送ったら何件記帳されますか?
答え

1件です(DBテストで確認)。

Q3整合性検査は不一致を自動で直しますか?
答え

直しません。検出して記録し、修正は取消・訂正や修復手続きで行います。

ここまで読めましたか?

完全に暗記する必要はありません。大切な考え方を説明できそうなら押してください。

SOURCE TRAIL

根拠と関連教材

CURRENT IMPLEMENTATIONは確認したrepository内の実装です。HISTORICAL IMPLEMENTATIONは導入・修正の履歴で、後続migrationによる再定義があり得ます。RELATED LESSONは教材への案内で、実装の一次Sourceではありません。ASSUMPTIONは仮定、UNKNOWNは未確認を表します。

確認基点: d02eae8914f39cbf06bfe422dc39c71886f82b3e / 2026-09-11。稼働環境への適用確認: UNKNOWN。パス実在の自動検査と、記述した技術的事実の確認は別です。

Implementation Status: IMPLEMENTED IN MINIBANK(この教材が扱うコードの範囲)

  • RELATED LESSON/docs/java-idempotencyIdempotencyの一般論
  • RELATED LESSON/docs/reconciliation照合と整合性検査(v7)
  • CURRENT IMPLEMENTATIONsupabase/migrations/20260924100000_v8_posting_engine.sqlposting.post_event / posting.find_idempotentBusiness Eventの記帳と冪等性
  • CURRENT IMPLEMENTATIONsupabase/migrations/20260924100000_v8_posting_engine.sqlposting.recompute_balances / posting.run_integrity残高再計算と整合性検査
  • CURRENT IMPLEMENTATIONscripts/banking/v8-posting.test.mjs冪等性・同時実行・取消・訂正・整合性検出のDBテスト