在分散式系統中,當多個獨立資料庫節點必須「要麼全部成功提交,要麼全部乾淨回滾」時,如何保證跨網路的原子性?
經典的解決方案是 兩階段提交協定(Two-Phase Commit, 2PC) 與其改良版 三階段提交協定(Three-Phase Commit, 3PC)。這兩大協定是 X/Open XA 分散式事務規範的理論基礎。
然而,在現代大規模互聯網與微服務環境下,2PC 與 3PC 卻因致命的同步阻塞(Synchronous Blocking)、協調者單點故障與網路分區腦裂而鮮少被直接用於高併發核心鏈路。
為了解決 2PC 鎖定資源過久的問題,工程界演化出了應用層的 TCC(Try-Confirm-Cancel) 模式。本文將全景拆解這三代強一致與業務補償協定的底層運作機制。
1. 兩階段提交(2PC):協定流程與致命瓶頸
2PC 由一個協調者(Coordinator) 與多個參與者(Participants / Resource Managers) 組成。
1.1 2PC 的三大致命缺陷
- 同步阻塞(Synchronous Blocking):
- 參與者在第一階段投出
Yes票後,會持續持有本地資料庫的行級排他鎖(Exclusive Locks)。 - 在收到協調者的第二階段
DoCommit之前,任何其他查詢或事務存取該行資料均會被死死卡住。在網路抖動時,鎖等待會迅速蔓延,引發全庫連線池枯竭。
- 參與者在第一階段投出
- 協調者單點故障(Single Point of Failure, SPOF):
- 若協調者在發送
Prepare成功後、準備發送DoCommit的瞬間發生硬體當機,所有參與者將永遠陷入等待與鎖定狀態,無法自主決定是提交還是回滾。
- 若協調者在發送
- 網路分區引發資料不一致(腦裂):
- 若協調者發送
DoCommit時發生網路分區,只有部分參與者收到了Commit指令並提交,而未收到指令的參與者在超時後可能被迫回滾,導致整個分散式叢集狀態分裂。
- 若協調者發送
2. 三階段提交(3PC):引入超時與預提交
為了緩解 2PC 的同步阻塞與單點當機問題,3PC 引入了逾時機制(Timeouts) 並將提交過程拆分為三段:
2.1 3PC 如何解決阻塞?
- 參與者自帶超時機制:在進入
PreCommit階段後,若參與者在等待第三階段DoCommit時發生協調者當機或網路中斷,參與者在等待超時後會自動預設執行Commit! - 理論缺陷:若協調者原先決定發送
Abort,但因網路分區只有部分節點收到Abort,其他超時節點自作主張執行了Commit,依然會導致嚴重的資料不一致。因此 3PC 在實際生產中極少被原生部署。
3. 業務層的 2PC:TCC 模式(Try-Confirm-Cancel)
為了解除底層資料庫層面的長週期行鎖,工程界將 2PC 的理念上移至應用業務層,形成了 TCC 模式:
| 階段 | 業務行為與責任 |
|---|---|
| 1. Try (預留資源) | 完成業務檢查,預留/凍結必要的業務資源 (如: 凍結餘額 100 元) |
| 2. Confirm (確認) | 真正執行業務操作,直接使用 Try 階段已凍結的資源 (不進行二次檢查) |
| 3. Cancel (取消) | 釋放 Try 階段凍結的預留資源,恢復原始狀態 |
3.1 TCC 轉帳案例深度拆解
假設從帳戶 A 向帳戶 B 轉帳 100 元:
3.2 TCC 實踐必須防禦的三大異常
- 空回滾(Empty Rollback):
- 網路延遲導致某服務的
Try請求根本未抵達,而協調者已觸發回滾發送了Cancel。 - 防禦:
Cancel必須先檢查是否存在對應的Try記錄,若無則標記為空回滾,不做任何資金釋放。
- 網路延遲導致某服務的
- 防懸掛(Anti-Suspension):
- 空回滾完成後,原本迷路的
Try請求此時突然延遲抵達。 - 防禦:
Try執行前必須檢查是否已存在Cancel記錄,若已取消則直接丟棄該請求。
- 空回滾完成後,原本迷路的
- 冪等性(Idempotency):
Confirm與Cancel可能因網路重試被多次執行,必須透過全域唯一事務 ID 保證重複呼叫無副作用。
4. 分散式事務技術選型全景矩陣
| 維度 | 2PC (XA 規範) | TCC 模式 | Saga 模式 |
|---|---|---|---|
| 一致性級別 | 強一致性 (ACID) | 最終一致性 | 最終一致性 |
| 資源鎖定時間 | 極長 (直到 Commit) | 極短 (本地立即提交) | 極短 (本地立即提交) |
| 程式碼侵入性 | 零 (資料庫層支援) | 極高 (需寫 3 個介面) | 中等 (需寫補償介面) |
| 系統吞吐量 | 極低 | 極高 | 極高 |
| 適用場景 | 內部極短跨庫交易 | 金融核心扣款/支付 | 跨服務訂單履約長流程 |
