分布式事務
銀行跨行轉賬業務是一個典型分布式事務場景,假設A需要跨行轉賬給B,那么就涉及兩個銀行的數據,無法通過一個數據庫的本地事務保證轉賬的ACID,只能夠通過分布式事務來解決。
分布式事務就是指事務的發起者、資源及資源管理器和事務協調者分別位於分布式系統的不同節點之上。
分布式事務的解決方案
兩階段提交/XA
XA是由X/Open組織提出的分布式事務的規范,XA規范主要定義了(全局)事務管理器(TM)和(局部)資源管理器(RM)之間的接口。本地的數據庫如mysql在XA中扮演的是RM角色
XA一共分為兩階段:
第一階段(prepare):即所有的參與者RM准備執行事務並鎖住需要的資源。參與者ready時,向TM報告已准備就緒。
第二階段 (commit/rollback):當事務管理者(TM)確認所有參與者(RM)都ready后,向所有參與者發送commit命令。
目前主流的數據庫基本都支持XA事務,包括mysql、oracle、sqlserver、postgre
XA 事務由一個或多個資源管理器(RM)、一個事務管理器(TM)和一個應用程序(ApplicationProgram)組成。
如果有任何一個參與者prepare失敗,那么TM會通知所有完成prepare的參與者進行回滾。
XA事務的特點是:
-
簡單易理解,開發較容易
-
對資源進行了長時間的鎖定,並發度低
SAGA
Saga是這一篇數據庫論文saga提到的一個方案。其核心思想是將長事務拆分為多個本地短事務,由Saga事務協調器協調,如果正常結束那就正常完成,如果某個步驟失敗,則根據相反順序一次調用補償操作。
SAGA事務的特點:
-
並發度高,不用像XA事務那樣長期鎖定資源
-
需要定義正常操作以及補償操作,開發量比XA大
-
一致性較弱,對於轉賬,可能發生A用戶已扣款,最后轉賬又失敗的情況
TCC
TCC分為3個階段
-
Try 階段:嘗試執行,完成所有業務檢查(一致性), 預留必須業務資源(准隔離性)
-
Confirm 階段:確認執行真正執行業務,不作任何業務檢查,只使用 Try 階段預留的業務資源,Confirm 操作要求具備冪等設計,Confirm 失敗后需要進行重試。
-
Cancel 階段:取消執行,釋放 Try 階段預留的業務資源。Cancel 階段的異常和 Confirm 階段異常處理方案基本上一致,要求滿足冪等設計。
TCC特點如下:
-
並發度較高,無長期資源鎖定。
-
開發量較大,需要提供Try/Confirm/Cancel接口。
-
一致性較好,不會發生SAGA已扣款最后又轉賬失敗的情況
-
TCC適用於訂單類業務,對中間狀態有約束的業務
本地消息表
寫本地消息和業務操作放在一個事務里,保證了業務和發消息的原子性,要么他們全都成功,要么全都失敗。
容錯機制:
-
扣減余額事務 失敗時,事務直接回滾,無后續步驟
-
輪序生產消息失敗, 增加余額事務失敗都會進行重試
本地消息表的特點:
-
長事務僅需要分拆成多個任務,使用簡單
-
生產者需要額外的創建消息表
-
每個本地消息表都需要進行輪詢
-
消費者的邏輯如果無法通過重試成功,那么還需要更多的機制,來回滾操作
事務消息
事務消息發送及提交:
-
發送消息(half消息)
-
服務端存儲消息,並響應消息的寫入結果
-
根據發送結果執行本地事務(如果寫入失敗,此時half消息對業務不可見,本地邏輯不執行)
-
根據本地事務狀態執行Commit或者Rollback(Commit操作發布消息,消息對消費者可見)
補償流程:
對沒有Commit/Rollback的事務消息(pending狀態的消息),從服務端發起一次“回查”
Producer收到回查消息,返回消息對應的本地事務的狀態,為Commit或者Rollback
事務消息方案與本地消息表機制非常類似,區別主要在於原先相關的本地表操作替換成了一個反查接口
事務消息特點如下:
-
長事務僅需要分拆成多個任務,並提供一個反查接口,使用簡單
-
消費者的邏輯如果無法通過重試成功,那么還需要更多的機制,來回滾操作
AT事務模式
這是阿里開源項目seata中的一種事務模式,在螞蟻金服也被稱為FMT。優點是該事務模式使用方式,類似XA模式,業務無需編寫各類補償操作,回滾由框架自動完成,缺點也類似AT,存在較長時間的鎖,不滿足高並發的場景。
分布式事務中的網絡異常
在分布式事務的各個環節都有可能出現網絡以及業務故障等問題,這些問題需要分布式事務的業務方做到防空回滾,冪等,防懸掛三個特性,下面以TCC事務說明這些異常情況:
空回滾:
在沒有調用 TCC 資源 Try 方法的情況下,調用了二階段的 Cancel 方法,Cancel 方法需要識別出這是一個空回滾,然后直接返回成功。
出現原因是當一個分支事務所在服務宕機或網絡異常,分支事務調用記錄為失敗,這個時候其實是沒有執行Try階段,當故障恢復后,分布式事務進行回滾則會調用二階段的Cancel方法,從而形成空回滾。
冪等:
由於任何一個請求都可能出現網絡異常,出現重復請求,所以所有的分布式事務分支,都需要保證冪等性
懸掛:
懸掛就是對於一個分布式事務,其二階段 Cancel 接口比 Try 接口先執行。
出現原因是在 RPC 調用分支事務try時,先注冊分支事務,再執行RPC調用,如果此時 RPC 調用的網絡發生擁堵,RPC 超時以后,TM就會通知RM回滾該分布式事務,可能回滾完成后,RPC 請求才到達參與者真正執行。