天天看點

微服務架構中分布式事務實作方案

提起微服務架構,不可避免的兩個話題就是服務治理和分布式事務。資料庫和業務子產品的垂直拆分為我們帶來了系統性能、穩定性和開發效率的提升的同時也引入了一些更複雜的問題,例如在資料一緻性問題上,我們不再能夠依賴資料庫的本地事務,對于一系列的跨庫寫入操作,如何保證其原子性,是微服務架構下不得不面對的問題。

一. 分布式事務解決方案

針對分布式系統的特點,基于不同的一緻性需求産生了不同的分布式事務解決方案,追求強一緻的兩階段送出、追求最終一緻性的柔性事務和事務消息等等。各種方案沒有絕對的好壞,抛開具體場景我們無法評價,更無法能做出合理選擇。在選擇分布式事務方案時,需要我們充分了解各種解決方案的原理和設計初衷,再結合實際的業務場景,進而做出科學合理的選擇。

二. 強一緻解決方案

2.1 兩階段送出

兩階段送出算法中有兩種角色:事務協調者和事務參與者,一個事務一般會涉及多個事務參與者,具體的兩階段過程如下圖所示:

第一階段:寫庫操作完成後協調者向所有參與者發送Prepare消息,詢問各參與者的本地事務是否可以送出,參與者根據自身情況向協調者傳回可以或不可以;

第二階段:協調者收到所有參與者的回報後,如果全部傳回的是可以送出則向所有參與者發送送出事務指令。隻要有一個參與者傳回的是不能送出,則向所有參與者發送復原指令。如下圖所示:

微服務架構中分布式事務實作方案

在上述的兩階段模型中,事務送出過程中有可能出現協調者或個别參與者當機的情況,但多數情況下參與事務的節點可以通過詢問其他節點得知事務狀态,做出正确的操作。但在極端情況下事務有可能處于未知狀态。我們分析下下面這個場景:當協調者發送送出指令後當機,而唯一收到送出指令的參與者完成送出後也當機了,此時沒有節點知道事務應該送出還是復原,事務處于未知狀态,是以在這種極端情況下可能造成資料的不一緻。針對兩階段的缺陷,又提出了三階段送出協定。

2.2  三階段送出

三階段送出是将第二階段拆分成預送出和确認送出兩個階段。這樣在事務送出過程中,無論哪個節點當機,隻要有一個存活節點處于預送出或是送出狀态我們都可以确定事務是可以送出的(第一階段已經确認事務可以送出),反之如果沒有處于這兩種狀态的節點,則復原事務。

微服務架構中分布式事務實作方案

從上面的分析可以看到,無論是兩階段還是三階段最後的“送出”都是一個耗時極短的操作,即使在分布式系統中失敗的機率也是非常小的,是以我們可以認為兩階段送出基本能夠保證分布式事務原子性。

三. 落地方案

上面介紹的隻是理論基礎,XA規範就是基于兩階段送出的理論模型提出的分布式事務規範,規範中的資料總管相當于事務參與者;事務管理器相當于事務協調者,目前很多主流的關系資料庫都實作了XA接口。

落地到實際應用中我們會發現兩階段送出存在的一些問題:

1. 資料庫産品要保證資料完成性,寫入需要加鎖,是以在整個分布式事務協調過程中可能造成資料庫資源鎖定時間過長,不适合并發高以及子事務生命周期較長的業務場景;

2. XA規範要求事務管理器本地記錄事務執行狀态,是以事務管理器作為有狀态服務不支援事務異地恢複;

XA能夠最大程度保證資料的一緻性,但在高并發場景下性能衰減非常嚴重,是以在資料一緻性需求上如果不是“強一緻”,不建議使用。

3.1 最終一緻性解決方案

在我們大多數的業務場景中,追求的都是資料的最終一緻性,業界也提出了很多柔性事務的解決方案,可以很大程度上保證資料的一緻性,我們可以根據實際場景來權衡使用。具體的解決方案有很多,總結其設計思路可以分為下面3種模型:

3.1.1 TCC(Try-Confirm-Cancel)

TCC将事務分為Try,Confirm,Cancel三個階段。

1. Try階段:嘗試執行業務,預留資源;

2. Confirm階段:确認執行業務,使用Try階段資源;

3. Cancel階段:取消執行業務,釋放Try階段預留的資源;

我們用一個轉賬彙款的業務場景,說明下TCC的具體過程。例如:張三給李四轉賬100元,一次轉賬業務由兩個本地事務組成:1、張三賬戶扣減100元;2、李四賬戶增加100元。

事務成功處理流程如圖3:

微服務架構中分布式事務實作方案

事務失敗處理流程如圖4:

微服務架構中分布式事務實作方案

Try階段:

       1、檢查張三賬戶,滿足要求賬戶扣減100元,記錄扣減事件(預留資源);

       2、檢查李四賬戶有效性;

Confirm:

       如果Try成功,李四賬戶增加100元,事務完成;

Cancel:

       如果Try失敗,張三賬戶增加100元,删除扣減事件記錄(釋放預留資源),事務取消。

從性能角度分析,TCC過程沒有對資源加鎖,對系統并發性能幾乎沒有影響,隻是會有些額外輔助操作。需要注意,在這個模型中要保證資料一緻性有兩個技術難點需要解決:

1. 需要有類似事務管理器的角色保證TCC過程的完整性;

2. Confirm和Cancel方法需要保證幂等(由于不可避免的重試操作必須要保證幂等);

TCC對業務侵入非常大,對RD同學十分不友好,業務改造成本相當高。

3.1.2 SAGA模型

SAGA模型把一個分布式事務拆分為多個本地事務,每個本地事務都有相應的執行子產品和補償子產品,當事務中任意一個本地事務出錯時,可以通過調用對應的補償方法恢複之前的事務,進而達到資料的最終的一緻性。SAGA的事務管理器負責在事務失敗時執行補償邏輯,可以通過調用執行子產品的逆向操作(例如執行子事務時同時生成逆向SQL)或調用業務開發人員提供的補償方法(需要保證補償的幂等性)來實作。

可以看到,SAGA雖然對業務造成一定的侵入,但當相對TCC已經有好很多了,而且,事務管理器理論上可以做到向後補償(撤銷所有已完成操作,恢複到事務開始狀态)或向前補償(繼續完成未完成事務,使業務請求得到成功處理,更符合業務預期)。

3.1.3 MQ事務消息

MQ事務消息對分布式事務模型進行了簡化,重點不再是保證所有子事務的原子性,而是保證本地事務和發送MQ消息的原子性,我們可以利用這一特點,将分布式事務轉化成本地事務和若幹發送MQ消息的操作,然後要求消費方確定消費成功。利用MQ事務消息,在系統中去掉了TCC和SAGA方案中的事務管理器角色,簡化了分布式事務模型,同時這也是對業務侵入最低最友好的方案(不用提供補償接口)。

當然這裡也有兩個基本前提:

1. MQ系統保證消息能不丢失;

2. 消費方確定消費幂等(保證不丢失,就很難避免重複消費)。

需要注意的是,MQ事務消息簡化了事務模型、降低了業務侵入,是以對資料一緻性的保證保障也就相對比較低了。

四. 總結

柔性事務解決方案中,雖然SAGA和TCC看上去可以保證資料的最終一緻性,但分布式系統的成産環境複雜多變,某些情況是可以導緻柔性事務機制失效的,是以無論使用那種方案,都需要最終的兜底政策,人工校驗,修複資料。

我們綜合對比下幾種分布式事務解決方案:

一緻性保證:XA > TCC = SAGA > 事務消息

業務友好性:XA > 事務消息 > SAGA > TCC

繼續閱讀