分佈式事務的幾種實現方式

      目前大部分的互聯網公司在設計總體架構的時候,都會按照業務模塊,將系統拆分紅不少小系統,例如訂單系統、卡券系統、支付系統等等,簡單來講,就是分而治之,這樣每一個人能夠專一維護本身的代碼。而後不一樣的小系統本身開發、測試和上線,都不會跟別人耦合在一塊兒,能夠本身獨立進行,很是的方便,大大簡化了大規模系統的開發成本。      數據庫

      然而有了多個子系統以後,分佈式事務應該怎麼來實現?下面就介紹一下分佈式事務的幾種實現方式。網絡

1、分佈式事務的概念

      分佈式事務指的是一個請求在多個系統的調用鏈當中如何確保數據一致。例如,一個支付請求,支付成功後,會回調請求訂單系統修改訂單狀態,會回調請求卡券系統修改卡券狀態。那麼若是回調請求由於網絡緣由丟失了,可能出現用戶支付了,訂單仍然顯示爲未支付狀態,卡券仍然在凍結中,沒法置爲已使用狀態。架構

2、2PC/3PC/TCC等分佈式事務協議

2PC兩階段提交協議

      2PC是很是經典的強一致、中心化的原子提交協議,協議中定義了兩類節點:一箇中心化協調者節點和多個參與者節點。2PC分爲兩個階段:分佈式

準備階段:性能

一、協調者向全部參與者發送事務內容,詢問是否能夠提交事務,並等待全部參與者答覆。測試

二、各參與者執行事務操做,將Undo和Redo信息記入事務日誌中(但不提交事務)。設計

三、如參與者執行成功,給協調者反饋YES,便可以提交;如執行失敗,給協調者反饋NO,即不可提交。日誌

提交階段:隊列

(全部參與者均反饋YES)事務

一、協調者向全部參與者發出正式提交事務的請求(即Commit請求)。

二、參與者執行Commit請求,並釋放整個事務期間佔用的資源。

三、各參與者向協調者反饋Ack完成的消息。

四、協調者收到全部參與者反饋的Ack消息後,即完成事務提交。

(任何一個參與者反饋NO)

一、協調者向全部參與者發出回滾請求(即Rollback請求)。

二、參與者使用階段1中的Undo信息執行回滾操做,並釋放整個事務期間佔用的資源。

三、各參與者向協調者反饋Ack完成的消息。

四、協調者收到全部參與者反饋的Ack消息後,即完成事務中斷。

2PC兩階段提交過程當中會遇到一些問題:

一、性能問題。從流程上咱們能夠看得出,其最大缺點就在於它的執行過程當中間,節點都處於阻塞狀態。各個操做數據庫的節點此時都佔用着數據庫資源,只有當全部節點準備完畢,事務協調者纔會通知進行全局提交,參與者進行本地事務提交後纔會釋放資源。這樣的過程會比較漫長,對性能影響比較大。

二、協調者單點故障問題。事務協調者是整個XA模型的核心,一旦事務協調者節點掛掉,會致使參與者收不到提交或回滾的通知,從而致使參與者節點始終處於事務沒法完成的中間狀態。

三、丟失消息致使的數據不一致問題。在第二個階段,若是發生局部網絡問題,一部分事務參與者收到了提交消息,另外一部分事務參與者沒收到提交消息,那麼就會致使節點間數據的不一致問題。

3PC三階段提交協議

      2PC的改進版本,其在兩階段提交的基礎上增長了CanCommit階段,並引入了超時機制。一旦事務參與者遲遲沒有收到協調者的Commit請求,就會自動進行本地commit,這樣相對有效地解決了協調者單點故障的問題。。

階段1:CanCommit
一、協調者向全部參與者發出包含事務內容的CanCommit請求,詢問是否能夠提交事務,並等待全部參與者答覆。
二、參與者收到CanCommit請求後,若是認爲能夠執行事務操做,則反饋YES並進入預備狀態,不然反饋NO。

階段2:PreCommit
事務預提交:(全部參與者均反饋YES時)
一、協調者向全部參與者發出PreCommit請求,進入準備階段。
二、參與者收到PreCommit請求後,執行事務操做,將Undo和Redo信息記入事務日誌中(但不提交事務)。
三、各參與者向協調者反饋Ack響應或No響應,並等待最終指令。
中斷事務:(任何一個參與者反饋NO,或者等待超時後協調者尚沒法收到全部參與者的反饋時)
一、協調者向全部參與者發出abort請求。
二、不管收到協調者發出的abort請求,或者在等待協調者請求過程當中出現超時,參與者均會中斷事務。

階段3:do Commit

提交事務:(全部參與者均反饋Ack響應時)

一、若是協調者處於工做狀態,則向全部參與者發出do Commit請求。

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

三、各參與者向協調者反饋Ack完成的消息。

四、協調者收到全部參與者反饋的Ack消息後,即完成事務提交。

中斷事務:(任何一個參與者反饋NO,或者等待超時後協調者尚沒法收到全部參與者的反饋時)  

一、若是協調者處於工做狀態,向全部參與者發出abort請求。  

二、參與者使用階段1中的Undo信息執行回滾操做,並釋放整個事務期間佔用的資源。  

三、各參與者向協調者反饋Ack完成的消息。  

四、協調者收到全部參與者反饋的Ack消息後,即完成事務中斷。

TCC補償事務協議

TCC 將事務提交分爲 Try - Confirm - Cancel 3個操做。

一、Try:預留業務資源/數據效驗

二、Confirm:確認執行業務操做

三、Cancel:取消執行業務操做

TCC事務處理流程和 2PC 二階段提交相似,不過 2PC一般都是在跨庫的DB層面,而TCC本質就是一個應用層面的2PC。

3、分佈式事務使用場景

一、基於消息實現的事務

基於消息實現的事務適用於分佈式事務的提交或回滾只取決於事務發起方的業務需求,其餘數據源的數據變動跟隨發起方進行的業務場景。

二、補償實現的事務

基於消息實現的事務並不能解決全部的業務場景,例如如下場景:某筆訂單完成時,同時扣掉用戶的現金。

這裏事務發起方是管理訂單庫的服務,但對整個事務是否提交併不能只由訂單服務決定,由於還要確保用戶有足夠的錢,才能完成這筆交易,而這個信息在管理現金的服務裏。這裏咱們能夠引入基於補償實現的事務,其流程以下:

  • 建立訂單數據,但暫不提交本地事務
  • 訂單服務發送遠程調用到現金服務,以扣除對應的金額
  • 上述步驟成功後提交訂單庫的事務

以上這個是正常成功的流程,異常流程須要回滾的話,將額外發送遠程調用到現金服務以加上以前扣掉的金額。

以上流程比基於消息隊列實現的事務的流程要複雜,同時開發的工做量也更多:

  • 編寫訂單服務裏建立訂單的邏輯
  • 編寫現金服務里扣錢的邏輯
  • 編寫現金服務裏補償返還的邏輯

能夠看到,該事務流程相對於基於消息實現的分佈式事務更爲複雜,須要額外開發相關的業務回滾方法,也失去了服務間流量削峯填谷的功能。但其僅僅只比基於消息的事務複雜多一點,若不能使用基於消息隊列的最終一致性事務,那麼能夠優先考慮使用基於補償的事務形態。

三、2PC事務

其適用於參與者較少,單個本地事務執行時間較少,而且參與者自身可用性很高的場景,不然,其極可能致使性能降低嚴重。

四、TCC實現的事務

相關文章
相關標籤/搜索