大きな画面での利用をおすすめします — アニメーションと操作がより快適になります。
入力

二相コミット(2PC)

二相コミットは、複数資源が一つの分散トランザクションに同じコミットまたは中止の決定を適用するためのプロトコルだ。全参加者の YES があって初めて調整者は COMMIT を決められ、一つの NO は先に YES と答えた側も含めて ABORT にする。

準備は資源をロックし、仮の結果を置く段階だ。YES は後の決定を受け入れる約束で、新値の適用ではない。調整者がその間に消えると、参加者は自票だけで確定も中止もできず、ロックを持って待つ場合がある。

準備、ロック、適用

画面は調整者 C が P1、P2、P3 へ個別に通信する星形で、参加者同士は話さない。P1 は口座 A、P2 は B、P3 は監査ログの資源管理者で、同じ行の三レプリカではない。二票の多数で第三の資源の同意を代替できない。

第一相で C が PREPARE を送り、各側がローカル検査をする。YES は準備を記録してロックし、current の横に proposed を置く。NO はこの例の資源をロックしない。二票では足りず、三票が集まってもまだ参加者の適用ではない。

第二相で C は COMMIT または ABORT を決め、全員へ同じものを送る。COMMIT の受信で提案値を current にして解放し、ABORT は提案を捨てて元値を保ち解放する。原子性は最終決定の一致で、全マシンが同時刻に表示を変える意味ではない。外部の可視性には隔離プロトコルも関わる。

不確定な待機窓は YES から決定受信までだ。他者が NO かもしれず独自コミットできず、C が既に COMMIT かもしれず独自中止もできない。既定は C が COMMIT、P1 は PREPARED、A は 100 の境界を見せる。

ステップ実行

All yes → commit の初期値は A=100、B=50、log=[]。T は A から 30 引き、B へ 30 加え、T を記録する。主要な境界は 7、9、10、12 だ。

  1. C は IDLE、P1–P3 は WORKING。票の帯は C のビューで、三枠目の後に need ALL YES がある。
  2. T が到着し C は WAITING。値とロックはまだ同じ。
  3. PREPARE が P1 へ届き、まだ WORKING。
  4. PREPARE が P2 へ届き、投票はまだゼロ。
  5. PREPARE が P3 へ届き、問いがそろう。
  6. P1 は 100−30=70 を検査して YES、A をロックする。紫の proposed=70、current=100。1 YES/3。
  7. P2 は B の 50→80 を準備してロックする。2 YES/3 では C はまだ待つ。
  8. P3 は []→[T] を準備し、3 YES/3。
  9. C が COMMIT を決める。まだ決定メッセージはなく、資源は準備状態。
  10. 待機窓。C は知っても P1 は他票と決定を知らず、A=100 のまま。単独で準備を終えられない。
  11. COMMIT が P1 へ移動中、P1 は PREPARED。
  12. P1 が受信して A=70 を適用、解放し COMMITTED。applied=1/3。
  13. COMMIT を P2 へ送る。
  14. P2 が B=80 を適用し、applied=2/3。
  15. COMMIT を P3 へ送る。
  16. P3 が log=[T] を適用し、applied=3/3。
  17. A=70、B=80、log=[T] で終える。先に全同意、その後各受信と適用だ。

One no → abort は A=20 で、P1 が残高不足の NO を返してロックしない。P2、P3 は YES で準備し、C は ABORT を決める。帯は applied でなく resolved を数える。全員へ中止が届いたが送金は起きない。P2 は proposed 80 を捨て、current はずっと 50 であり、一度外へ 80 を公開して戻すわけではない。

Coordinator crash は C の COMMIT 決定まで同じで、送信前に失う。C のログビューが使えないのであり、実耐久ログが削除されたという意味ではない。P1 は自分の YES だけを知り、決定は未受信。P1–P3 は PREPARED とロックを保つ。復旧を表示しないため待機で終える。

待つ理由

Raft の三対五は同じログを複製し、重なる多数とログ規則で履歴を保つ。2PC は三つの異なる資源を変え、監査ログが拒否すれば口座だけを動かしてはいけない。全 YES が必要だ。

調整者の決定を Raft ログに置けば単一調整者の故障影響を減らせるが、COMMIT の複製は NO の資源を無視する許可ではない。多数複製と全資源準備は別条件である。

YES 後は最終決定への約束があり、遅延だけで取り消せない。調整者はコミットを決める前なら投票タイムアウトで中止を選べるが、準備済み参加者の一方的中止とは違う。ここはタイムアウト、復旧ログ、presumed abort、協調終了、3PC などの追加・別規則を省く。

適する場面

独立資源をまたぐ統一結果が必要で、障害時の準備資源のブロックを許容できる場合に適する。口座と監査記録は、片方の欠落を部分成功としてよいとは限らない例だ。

段階ごとのローカル確定と後の補償を許すなら saga を検討できるが、途中状態や補償失敗を含む別の約束となる。参加者が同じログの複製なら合意複製の問題で、資源全員投票を誤用しない。

本課のメッセージは N に線形で、各参加者に PREPARE、一票、一決定。YES から決定までロックを持つ。準備と投票は並行でき、N 増加はメッセージ、ロック、遅い参加者の影響を増やすが固定の直列相数は増やさない。四人なら四 YES が必要になる。

境界ケース

  • 2 YES+1 NO なら中止し、二つの YES 側も準備を捨て解放する。
  • A=100 は準備でき、A=20 は拒否して当該ロックを取らない。
  • decideCommit 後も A=100。決定とローカル適用は別だ。
  • 既に拒否した P1 も ABORT を受け、取り消す新更新はない。
  • C の私的決定後の故障で、参加者は結果を知らない。この全 YES 履歴なら独自適用が偶然正しくても、未知の NO がある履歴なら壊れる。観察者の後知恵を規則にできない。

よくある間違い

  • 二票の多数でコミットする。境界は三枠の後で、全 YES が必要だ。
  • 紫の proposed 70 を適用済みと読む。current の 100→70 は投票でなく applyCommit。
  • PREPARED が待ち時間だけで独自決定し、未知の決定を無視する。
  • 画面の参加者が勝手に新調整者を選ぶと考える。横方向の通信や復旧を含まず、他方式には追加定義が必要だ。
  • Raft と 2PC の閾値を入れ替える。調整者を複製しても資源の全同意規則は変わらない。

モデルの範囲

C 一つ、参加者三つ、焦点 RPC 一つずつ。決定 ACK、入れ子のトランザクション、投票タイムアウト、presumed-abort 最適化、3PC、協調終了、調整者復旧、耐久ログの詳細なフラッシュ時刻は省く。故障例はログを再生せず待機を残す。全投票と準備後の不確定窓は実 2PC の性質で、時間は証拠と適用を分けるために組み立てる。