調研 | 5種分佈式事務解決方案優缺點對比

背景

 

分佈式事務是企業集成中的一個技術難點,也是每一個分佈式系統架構中都會涉及到的一個東西,特別是在微服務架構中,幾乎可以說是無法避免。

 

ACID

指數據庫事務正確執行的四個基本要素:

  • 原子性(Atomicity)

  • 一致性(Consistency)

  • 隔離性(Isolation)

  • 持久性(Durability)

 

CAP

CAP原則又稱CAP定理,指的是在一個分佈式系統中,一致性(Consistency)、可用性(Availability)、分區容忍性(Partition tolerance)。CAP 原則指的是,這三個要素最多隻能同時實現兩點,不可能三者兼顧。

  • 一致性:在分佈式系統中的所有數據備份,在同一時刻是否同樣的值。

  • 可用性:在集羣中一部分節點故障後,集羣整體是否還能響應客戶端的讀寫請求。

  • 分區容忍性:以實際效果而言,分區相當於對通信的時限要求。系統如果不能在時限內達成數據一致性,就意味着發生了分區的情況,必須就當前操作在C和A之間做出選擇。

 

BASE理論

BASE理論是對CAP中的一致性和可用性進行一個權衡的結果,理論的核心思想就是:我們無法做到強一致,但每個應用都可以根據自身的業務特點,採用適當的方式來使系統達到最終一致性。

  • Basically Available(基本可用)

  • Soft state(軟狀態)

  • Eventually consistent(最終一致性)

 

 

解決方案

 

01

兩階段提交(2PC)

兩階段提交2PC是分佈式事務中最強大的事務類型之一,兩段提交就是分兩個階段提交,第一階段詢問各個事務數據源是否準備好,第二階段才真正將數據提交給事務數據源。

 

爲了保證該事務可以滿足ACID,就要引入一個協調者(Cooradinator)。其他的節點被稱爲參與者(Participant)。協調者負責調度參與者的行爲,並最終決定這些參與者是否要把事務進行提交。處理流程如下:

 

 

  • 階段一

a) 協調者向所有參與者發送事務內容,詢問是否可以提交事務,並等待答覆。

b) 各參與者執行事務操作,將 undo 和 redo 信息記入事務日誌中(但不提交事務)。

c) 如參與者執行成功,給協調者反饋 yes,否則反饋 no。

 

  •  階段二

如果協調者收到了參與者的失敗消息或者超時,直接給每個參與者發送回滾(rollback)消息;否則,發送提交(commit)消息。兩種情況處理如下:

 

情況1:當所有參與者均反饋 yes,提交事務

a) 協調者向所有參與者發出正式提交事務的請求(即 commit 請求)。

b) 參與者執行 commit 請求,並釋放整個事務期間佔用的資源。

c) 各參與者向協調者反饋 ack(應答)完成的消息。

d) 協調者收到所有參與者反饋的 ack 消息後,即完成事務提交。

 

情況2:當有一個參與者反饋 no,回滾事務

a) 協調者向所有參與者發出回滾請求(即 rollback 請求)。

b) 參與者使用階段 1 中的 undo 信息執行回滾操作,並釋放整個事務期間佔用的資源。

c) 各參與者向協調者反饋 ack 完成的消息。

d) 協調者收到所有參與者反饋的 ack 消息後,即完成事務。

 

  • 問題

1) 性能問題:所有參與者在事務提交階段處於同步阻塞狀態,佔用系統資源,容易導致性能瓶頸。

2) 可靠性問題:如果協調者存在單點故障問題,或出現故障,提供者將一直處於鎖定狀態。

3) 數據一致性問題:在階段 2 中,如果出現協調者和參與者都掛了的情況,有可能導致數據不一致。

 

優點:儘量保證了數據的強一致,適合對數據強一致要求很高的關鍵領域。(其實也不能100%保證強一致)。

 

缺點:實現複雜,犧牲了可用性,對性能影響較大,不適合高併發高性能場景。

 

02

三階段提交(3PC)

三階段提交是在二階段提交上的改進版本,3PC最關鍵要解決的就是協調者和參與者同時掛掉的問題,所以3PC把2PC的準備階段再次一分爲二,這樣三階段提交。處理流程如下:

 

 

  • 階段一

a) 協調者向所有參與者發出包含事務內容的 canCommit 請求,詢問是否可以提交事務,並等待所有參與者答覆。

b) 參與者收到 canCommit 請求後,如果認爲可以執行事務操作,則反饋 yes 並進入預備狀態,否則反饋 no。

 

  • 階段二

協調者根據參與者響應情況,有以下兩種可能。

 

情況1:所有參與者均反饋 yes,協調者預執行事務

a) 協調者向所有參與者發出 preCommit 請求,進入準備階段。

b) 參與者收到 preCommit 請求後,執行事務操作,將 undo 和 redo 信息記入事務日誌中(但不提交事務)。

c) 各參與者向協調者反饋 ack 響應或 no 響應,並等待最終指令。

 

情況2:只要有一個參與者反饋 no,或者等待超時後協調者尚無法收到所有提供者的反饋,即中斷事務

a) 協調者向所有參與者發出 abort 請求。

b) 無論收到協調者發出的 abort 請求,或者在等待協調者請求過程中出現超時,參與者均會中斷事務。

 

  • 階段三

該階段進行真正的事務提交,也可以分爲以下兩種情況。

 

情況 1:所有參與者均反饋 ack 響應,執行真正的事務提交

a) 如果協調者處於工作狀態,則向所有參與者發出 do Commit 請求。

b) 參與者收到 do Commit 請求後,會正式執行事務提交,並釋放整個事務期間佔用的資源。

c) 各參與者向協調者反饋 ack 完成的消息。

d) 協調者收到所有參與者反饋的 ack 消息後,即完成事務提交。

 

情況2:只要有一個參與者反饋 no,或者等待超時後協調組尚無法收到所有提供者的反饋,即回滾事務。

a) 如果協調者處於工作狀態,向所有參與者發出 rollback 請求。

b) 參與者使用階段 1 中的 undo 信息執行回滾操作,並釋放整個事務期間佔用的資源。

c) 各參與者向協調組反饋 ack 完成的消息。

d) 協調組收到所有參與者反饋的 ack 消息後,即完成事務回滾。

 

優點:相比二階段提交,三階段提交降低了阻塞範圍,在等待超時後協調者或參與者會中斷事務。避免了協調者單點問題。階段 3 中協調者出現問題時,參與者會繼續提交事務。

 

缺點:數據不一致問題依然存在,當在參與者收到 preCommit 請求後等待 do commite 指令時,此時如果協調者請求中斷事務,而協調者無法與參與者正常通信,會導致參與者繼續提交事務,造成數據不一致。

 

03

補償事務(TCC)

TCC 是服務化的二階段編程模型,採用的補償機制:

 

 

條件:

  • 需要實現確認和補償邏輯

  • 需要支持冪等

 

處理流程:

a) Try 階段主要是對業務系統做檢測及資源預留。

這個階段主要完成:

  • 完成所有業務檢查( 一致性 ) 。

  • 預留必須業務資源( 準隔離性 ) 。

  • Try 嘗試執行業務。

 

b) Confirm 階段主要是對業務系統做確認提交。

Try階段執行成功並開始執行 Confirm階段時,默認 Confirm階段是不會出錯的。即:只要Try成功,Confirm一定成功。

 

c) Cancel 階段主要是在業務執行錯誤,需要回滾的狀態下執行的業務取消,預留資源釋放。

 

優點:

  • 性能提升:具體業務來實現控制資源鎖的粒度變小,不會鎖定整個資源。

  • 數據最終一致性:基於 Confirm 和 Cancel 的冪等性,保證事務最終完成確認或者取消,保證數據的一致性。

  • 可靠性:解決了 XA 協議的協調者單點故障問題,由主業務方發起並控制整個業務活動,業務活動管理器也變成多點,引入集羣。

 

缺點:TCC 的 Try、Confirm 和 Cancel 操作功能要按具體業務來實現,業務耦合度較高,提高了開發成本。

 

04

本地消息表(消息隊列)

其核心思想是將分佈式事務拆分成本地事務進行處理。

 

方案通過在消費者額外新建事務消息表,消費者處理業務和記錄事務消息在本地事務中完成,輪詢事務消息表的數據發送事務消息,提供者基於消息中間件消費事務消息表中的事務。

 

 

條件: 

  • 服務消費者需要創建一張消息表,用來記錄消息狀態。

  • 服務消費者和提供者需要支持冪等。

  • 需要補償邏輯。

  • 每個節點上起定時線程,檢查未處理完成或發出失敗的消息,重新發出消息,即重試機制和冪等性機制。

 

處理流程:

1. 服務消費者把業務數據和消息一同提交,發起事務。

2. 消息經過MQ發送到服務提供方,服務消費者等待處理結果。

3. 服務提供方接收消息,完成業務邏輯並通知消費者已處理的消息。

 

容錯處理情況如下:

  • 當步驟1處理出錯,事務回滾,相當於什麼都沒有發生。

  • 當步驟2、3處理出錯,由於消息保存在消費者表中,可以重新發送到MQ進行重試。

  • 如果步驟3處理出錯,且是業務上的失敗,服務提供者發送消息通知消費者事務失敗,且此時變爲消費者發起回滾事務進行回滾邏輯。

 

優點:從應用設計開發的角度實現了消息數據的可靠性,消息數據的可靠性不依賴於消息中間件,弱化了對 MQ 中間件特性的依賴。

 

缺點:與具體的業務場景綁定,耦合性強,不可公用。消息數據與業務數據同庫,佔用業務系統資源。業務系統在使用關係型數據庫的情況下,消息服務性能會受到關係型數據庫併發性能的侷限。

 

MQ事務消息(最終一致性)

支持事務消息的MQ,其支持事務消息的方式採用類似於二階段提交。

 

基於 MQ 的分佈式事務方案其實是對本地消息表的封裝,將本地消息表基於 MQ 內部,其他方面的協議基本與本地消息表一致。

 

 

條件:

a) 需要補償邏輯

b) 業務處理邏輯需要冪等

 

處理流程:

c) 消費者向MQ發送half消息。

d) MQ Server將消息持久化後,向發送方ack確認消息發送成功。

e) 消費者開始執行事務邏輯。

f) 消費者根據本地事務執行結果向MQ Server提交二次確認或者回滾。

g) MQ Server收到commit狀態則將half消息標記可投遞狀態。

h) 服務提供者收到該消息,執行本地業務邏輯。返回處理結果。

 

優點:

  • 消息數據獨立存儲,降低業務系統與消息系統之間的耦合。

  • 吞吐量優於本地消息表方案。

 

缺點:

  • 一次消息發送需要兩次網絡請求(half消息 + commit/rollback)。

  • 需要實現消息回查接口。

 

05

Sagas事務模型(最終一致性)

Saga模式是一種分佈式異步事務,一種最終一致性事務,是一種柔性事務,有兩種不同的方式來實現saga事務,最流行的兩種方式是:

 

一、 事件/編排Choreography:沒有中央協調器(沒有單點風險)時,每個服務產生並聆聽其他服務的事件,並決定是否應採取行動。

 

該實現第一個服務執行一個事務,然後發佈一個事件。該事件被一個或多個服務進行監聽,這些服務再執行本地事務併發布(或不發佈)新的事件,當最後一個服務執行本地事務並且不發佈任何事件時,意味着分佈式事務結束,或者它發佈的事件沒有被任何Saga參與者聽到都意味着事務結束。

 

 

處理流程:

  1. 訂單服務保存新訂單,將狀態設置爲pengding掛起狀態,併發布名爲ORDER_CREATED_EVENT的事件。

  2. 支付服務監聽ORDER_CREATED_EVENT,並公佈事件BILLED_ORDER_EVENT。

  3. 庫存服務監聽BILLED_ORDER_EVENT,更新庫存,併發布ORDER_PREPARED_EVENT。

  4. 貨運服務監聽ORDER_PREPARED_EVENT,然後交付產品。最後,它發佈ORDER_DELIVERED_EVENT。

  5. 最後,訂單服務偵聽ORDER_DELIVERED_EVENT並設置訂單的狀態爲concluded完成。

 

假設庫存服務在事務過程中失敗了。進行回滾:

  1. 庫存服務產生PRODUCT_OUT_OF_STOCK_EVENT

  2. 訂購服務和支付服務會監聽到上面庫存服務的這一事件:

    ①支付服務會退款給客戶。

    ②訂單服務將訂單狀態設置爲失敗。

 

優點:事件/編排是實現Saga模式的自然方式; 它很簡單,容易理解,不需要太多的努力來構建,所有參與者都是鬆散耦合的,因爲他們彼此之間沒有直接的耦合。如果您的事務涉及2至4個步驟,則可能是非常合適的。

 

二、 命令/協調orchestrator:中央協調器負責集中處理事件的決策和業務邏輯排序。

 

saga協調器orchestrator以命令/回覆的方式與每項服務進行通信,告訴他們應該執行哪些操作。

 

 

  1. 訂單服務保存pending狀態,並要求訂單Saga協調器(簡稱OSO)開始啓動訂單事務。

  2. OSO向收款服務發送執行收款命令,收款服務回覆Payment Executed消息。

  3. OSO向庫存服務發送準備訂單命令,庫存服務將回復OrderPrepared消息。

  4. OSO向貨運服務發送訂單發貨命令,貨運服務將回復Order Delivered消息。

 

OSO訂單Saga協調器必須事先知道執行“創建訂單”事務所需的流程(通過讀取BPM業務流程XML配置獲得)。如果有任何失敗,它還負責通過向每個參與者發送命令來撤銷之前的操作來協調分佈式的回滾。當你有一箇中央協調器協調一切時,回滾要容易得多,因爲協調器默認是執行正向流程,回滾時只要執行反向流程即可。

 

優點:

  • 避免服務之間的循環依賴關係,因爲saga協調器會調用saga參與者,但參與者不會調用協調器。

  • 集中分佈式事務的編排。

  • 只需要執行命令/回覆(其實回覆消息也是一種事件消息),降低參與者的複雜性。

  • 在添加新步驟時,事務複雜性保持線性,回滾更容易管理。

  • 如果在第一筆交易還沒有執行完,想改變有第二筆事務的目標對象,則可以輕鬆地將其暫停在協調器上,直到第一筆交易結束。

 

缺點:協調器中集中太多邏輯的風險。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章