分散式事務最經典的七種解決方案
分散式事務
銀行跨行轉賬業務是一個典型分散式事務場景,假設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 請求才到達參與者真正執行。