例如在下單場景下,庫存和訂單若是不在同一個節點上,就涉及分佈式事務。html
解決方案
在分佈式系統中,要實現分佈式事務,無外乎那幾種解決方案。程序員
1、兩階段提交(2PC)
兩階段提交(Two-phase Commit,2PC),經過引入協調者(Coordinator)來協調參與者的行爲,並最終決定這些參與者是否要真正執行事務。數據庫
1. 運行過程
1.1 準備階段
協調者詢問參與者事務是否執行成功,參與者發回事務執行結果。網絡
1.2 提交階段
若是事務在每一個參與者上都執行成功,事務協調者發送通知讓參與者提交事務;不然,協調者發送通知讓參與者回滾事務。異步
須要注意的是,在準備階段,參與者執行了事務,可是還未提交。只有在提交階段接收到協調者發來的通知後,才進行提交或者回滾。分佈式
2. 存在的問題
2.1 同步阻塞 全部事務參與者在等待其它參與者響應的時候都處於同步阻塞狀態,沒法進行其它操做。ui
2.2 單點問題 協調者在 2PC 中起到很是大的做用,發生故障將會形成很大影響。特別是在階段二發生故障,全部參與者會一直等待狀態,沒法完成其它操做。spa
2.3 數據不一致 在階段二,若是協調者只發送了部分 Commit 消息,此時網絡發生異常,那麼只有部分參與者接收到 Commit 消息,也就是說只有部分參與者提交了事務,使得系統數據不一致。htm
2.4 太過保守 任意一個節點失敗就會致使整個事務失敗,沒有完善的容錯機制。中間件
2、補償事務(TCC)
TCC 其實就是採用的補償機制,其核心思想是:針對每一個操做,都要註冊一個與其對應的確認和補償(撤銷)操做。它分爲三個階段:
-
Try 階段主要是對業務系統作檢測及資源預留
-
Confirm 階段主要是對業務系統作確認提交,Try階段執行成功並開始執行 Confirm階段時,默認 Confirm階段是不會出錯的。即:只要Try成功,Confirm必定成功。
-
Cancel 階段主要是在業務執行錯誤,須要回滾的狀態下執行的業務取消,預留資源釋放。
舉個例子,假入 Bob 要向 Smith 轉帳,思路大概是: 咱們有一個本地方法,裏面依次調用
- 首先在 Try 階段,要先調用遠程接口把 Smith 和 Bob 的錢給凍結起來。
- 在 Confirm 階段,執行遠程調用的轉帳的操做,轉帳成功進行解凍。
- 若是第2步執行成功,那麼轉帳成功,若是第二步執行失敗,則調用遠程凍結接口對應的解凍方法 (Cancel)。
優勢: 跟2PC比起來,實現以及流程相對簡單了一些,但數據的一致性比2PC也要差一些
缺點: 缺點仍是比較明顯的,在2,3步中都有可能失敗。TCC屬於應用層的一種補償方式,因此須要程序員在實現的時候多寫不少補償的代碼,在一些場景中,一些業務流程可能用TCC不太好定義及處理。
3、本地消息表(異步確保)
本地消息表與業務數據表處於同一個數據庫中,這樣就能利用本地事務來保證在對這兩個表的操做知足事務特性,而且使用了消息隊列來保證最終一致性。
- 在分佈式事務操做的一方完成寫業務數據的操做以後向本地消息表發送一個消息,本地事務能保證這個消息必定會被寫入本地消息表中。
- 以後將本地消息表中的消息轉發到 Kafka 等消息隊列中,若是轉發成功則將消息從本地消息表中刪除,不然繼續從新轉發。
- 在分佈式事務操做的另外一方從消息隊列中讀取一個消息,並執行消息中的操做。
優勢: 一種很是經典的實現,避免了分佈式事務,實現了最終一致性。
缺點: 消息表會耦合到業務系統中,若是沒有封裝好的解決方案,會有不少雜活須要處理。
4、MQ 事務消息
有一些第三方的MQ是支持事務消息的,好比RocketMQ,他們支持事務消息的方式也是相似於採用的二階段提交,可是市面上一些主流的MQ都是不支持事務消息的,好比 RabbitMQ 和 Kafka 都不支持。
以阿里的 RocketMQ 中間件爲例,其思路大體爲:
第一階段Prepared消息,會拿到消息的地址。 第二階段執行本地事務,第三階段經過第一階段拿到的地址去訪問消息,並修改狀態。
也就是說在業務方法內要想消息隊列提交兩次請求,一次發送消息和一次確認消息。若是確認消息發送失敗了RocketMQ會按期掃描消息集羣中的事務消息,這時候發現了Prepared消息,它會向消息發送者確認,因此生產方須要實現一個check接口,RocketMQ會根據發送端設置的策略來決定是回滾仍是繼續發送確認消息。這樣就保證了消息發送與本地事務同時成功或同時失敗。
優勢: 實現了最終一致性,不須要依賴本地數據庫事務。
缺點: 實現難度大,主流MQ不支持,RocketMQ事務消息部分代碼也未開源。
總結
經過本文咱們總結並對比了幾種分佈式分解方案的優缺點,分佈式事務自己是一個技術難題,是沒有一種完美的方案應對全部場景的,具體仍是要根據業務場景去抉擇吧。阿里RocketMQ去實現的分佈式事務,如今也有除了不少分佈式事務的協調器,好比LCN等,你們能夠多去嘗試。