一文徹底搞懂分佈式事務

引子

在分佈式系統中,由於業務的劃分導致了原本單機系統本地完成的事務被分割在了不同的微服務中,這也帶來了分佈式情況下事務如何解決?如何保證不同微服務之間的事務保持原子性?一致性?隔離性?持久性?那麼分佈式事務有哪些已經成熟的解決方案呢?下面我們來一起看看。

2pc: 兩階段提交協議。

首先來看2pc的概念:  這是一個簡單的兩階段提交協議的分佈式事務。通過一個事務協調器,在prepare 階段詢問所有分佈式事務參與者是否已經準備就緒。然後在commit/roolback階段發起真正的提交或回滾,從而完成一次分佈式事務。

接下來我們來看2pc的流程圖,具體來解析下2pc如何處理的。此過程 涉及的參與方: 協調者,參與者。採用了cap原理中的 cp 。cap: 分佈式理論的一個概念,簡單介紹下: CAP : 一致性,可用性,分區容忍性。在任何一個分佈式系統中都不可避免會遇到p,即系統之間網絡故障,導致不通。即發生了分區,此時我們只能在C和A中選擇一個,這就是著名的CAP理論。

  • 通過上圖我們可以得到如下結論:
  • 優點: 方案成熟,處理過程簡單清晰。強一致性。
  • 缺點: 阻塞,如果任何一個參與者掛了,則其他參與者都是處於一直阻塞等待狀態。commit,rollback 無法確保都會到達所有參與者。可能由於網絡等原因導致,這樣只有部分參與者收到commit信息,導致數據不一致。
  • 問題:
  • 單點問題: 協調者掛了。可以適用主備模式,防止單點。協調者掛了選舉從切換爲主協調者。
  • 參與者掛了: 協調者收不到參與者的響應,可以設置超時機制。超時了則認爲返回NO,則想所有參與者發送rollback,防止其他參與者一直等待。也可以加入重試機制,超時重試幾次後,才認爲其返回爲No。這樣保持了強一致性。
  • 部分提交: 只有一部分參與者收到提交回滾消息。導致數據不一致。這裏可以加入確認機制,確認參與者實現了自己的事務提交,沒有收到確認信息的採用補償機制進行重試。達到數據的最終一致性。
  • 適應場景: 需要保持分佈式事務強一致性的場景。比如訂單和賬戶扣款服務。雙方服務高可用。

 3pc:   三階段提交協議,解決2pc的阻塞問題。分爲canCommit,prepareCommit,doCommit.

多加了一層cancommit,詢問參與者是否能完成自己的事務。獲取數據庫鎖。其他的和2pc一樣,準備階段一分爲2,爲在事務真正提交回滾前,各個參與者到達一致性狀態提供了保障。

  • canCommit: 這一階段協調者向參與者詢問是否可以預提交事務,得到所有的參與者回覆Yes,則進入prepareCommit階段。
  • prepareCommit: 這一階段和2pc的prepare階段大致一樣。不一樣的地方在於,參與者有了超時機制,即協調者和參與者都有了超時機制。在任何一方掛掉的情況下,另一方不會傻傻的一直等待響應了。這也是防止了一直阻塞的情況。
  • doCommit: 和2pc 的第二階段一樣。

TCC: 基於2pc 改進的基於補償實現的分佈式事務解決方案。

tcc 分爲三個階段,try階段,confirm階段,cancel階段。通過對每一步操作的添加的確認或撤銷操作,從而實現即失敗異常時的補償機制。達到數據一致性的目的。

try階段:檢查參與者是否滿足業務條件,可以繼續向下走。比如 轉賬時對賬戶及其餘額的檢查,對收款方賬戶的檢查。

confirm: try階段成功後,通過confirm對參與方進行事務提交。try成功,則confirm一定成功。

cancel: try失敗了或有異常,則取消之前參與方對資源的鎖定,或者回滾已經處理的業務。

那麼現實中採用的流行的解決方案是哪些呢?讓我們一起來看下ebay 提供的本地消息表的解決方案,還有分佈式事務消息的解決方案,具體的場景不同,我們可以選擇不同的方案。當然,最大程度避免使用分佈式事務自然最好。

ebay本地消息表分佈式事務解決方案。

本地消息表的思想是: 通過將分佈式事務的分解爲一個個本地事務,通過消息來串聯起一個個本地事務,來達到實現分佈式事務的目的。這樣可以基於mysql這樣的關係數據庫來實現。 我們來看下流程圖:

 

  • 本地消息表的實現方式,整體看來比較清晰簡單。本地事務的可靠性,保證了消息寫入的可靠。並且可以利用MQ的高可用,時效高,削峯等特性,可以看到效果是不錯的。目前有去哪兒,支付寶,蘑菇街等知名互聯網公司在使用。也給我們提供了一個參考。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章