1. 程式人生 > >趁熱打鐵-再談分散式事務

趁熱打鐵-再談分散式事務

繼上一篇講 MySQL InnoDB 下的事務之後我們趁熱打鐵,繼續跟進分散式事務。 分散式事務主要解決分散式一致性的問題。說到底就是資料的分散式操作導致僅依靠本地事務無法保證原子性。與單機版的事務不同的是,單機是把多個命令打包成一個統一處理,分散式事務是將多個機器上執行的命令打包成一個命令統一處理。 上一篇我們講 InnoDB 下的事務,MySQL 提供了redo log,undo log, Read View,兩階段提交,MVCC 機制等等來保障事務的安全。分散式事務是不是更難呢?拭目以待。 #### 常見的分散式事務場景 分散式事務其實就在我們身邊,你一直在用,但是你卻一直不注意它。 ##### 轉賬 扣你賬戶的餘額,增加別人賬戶餘額,如果只扣了你的,別人沒增加這是失敗;如果沒扣你的錢別人也增加了那銀行的賠錢。 ##### 下訂單/扣庫存 電商系統中這是很常見的一個場景,使用者下單成功了,店家沒收到單,不發貨;使用者取消了訂單,但是店家卻看到了訂單,發了貨。 ##### 分庫分表場景 當我們的資料量大了之後,我們可能會部署很多獨立的資料庫,但是你的一個邏輯可能會同時操作很多個數據庫的表,這時候該如何保證所有的操作要麼成功,要麼失敗。 ##### 分散式系統呼叫問題 微服務的拆分讓各個系統各司其職,但是帶來的也有很多痛苦,一個操作可能會伴隨很多的外部請求,如果某一個外部系統掛掉了,之前操作已完成的這些是否需要回滾。 針對上面這些問題,我們前面學過的資料庫4大特性:ACID 似乎在這裡想要達到就變得很困難,單機情況下你還可以通過鎖和日誌機制來控制資料,在分散式場景又該如何實現呢?在不同的分散式應用架構下,實現一個分散式事務要考慮的問題並不完全一樣,比如對多資源的協調、事務的跨服務傳播等,實現機制也是複雜多變。儘管有這麼多工程細節需要考慮,但分散式事務最核心的還是其 ACID 特性,只是這種 ACID 變換了場景。 #### 分散式理論 ##### CAP 定理 傳統的 ACID 模型肯定無法解決分散式環境下的挑戰,基於此加州大學伯克利分校 Eric Brewer教授提出 CAP 定理,他指出 現代 WEB 服務無法同時滿足以下 3 個屬性: - 一致性(Consistency) : 所有的客戶端都能返回最新的操作。 - 可用性(Availability) : 非故障的節點在合理的時間內返回合理的響應(不是錯誤和超時的響應)。 - 分割槽容錯性(Partition tolerance) : 即使出現單個元件無法可用,操作依然可以完成。 關於一致性的理解後面分出來三個方向: - 強一致:任何一次讀都能讀到某個資料的最近一次寫的資料。系統中的所有程序,看到的操作順序,都和全域性時鐘下的順序一致。簡言之,在任意時刻,所有節點中的資料是一樣的。 - 弱一致:資料更新後,如果能容忍後續的訪問只能訪問到部分或者全部訪問不到,則是弱一致性。 - 最終一致:不保證在任意時刻任意節點上的同一份資料都是相同的,但是隨著時間的遷移,不同節點上的同一份資料總是在向趨同的方向變化。簡單說,就是在一段時間後,節點間的資料會最終達到一致狀態。 關於一致性的理解不同,後面對於 CAP 理論的實現就有所不同。 另外 Eric Brewer教授指出現代 WEB 服務無法同時滿足這 3 個屬性,說的是無法同時滿足,那這是為什麼呢? 如果在某個分散式系統中無副本,那麼必然滿足強一致性,同時也滿足可用性,但是如果這個資料宕機了,那麼可用性就得不到保證。 如果一個系統滿足 AP,那麼一致性又得不到保證。所以 CAP 原則的精髓就是要麼 AP,要麼 CP,要麼 AC,但是不存在 CAP。 ##### BASE 定理 基於前面提到的 CAP,反正我們都無法同時滿足CAP,設計系統的最高目的就是讓他跑下去不出錯,那麼是不是可以不要求強一致性,最終讓他一致即可。所以後面又提出來了 BASE 定理: - Basically Available(基本可用) - Soft state(軟狀態) - Eventually consistent(最終一致性) 基於現在大型分散式系統的複雜性,我們無法保證服務永遠達到999,那麼是否可以取捨,核心服務達到999,非核心服務允許掛為了保全核心服務。另外在非核心服務 down 機過程中允許系統暫時出現不一致但是這個不一致並不影響系統的核心功能使用。 最終系統恢復,所有服務一起修復資料,最終達到一致的狀態。 業內通常把嚴格遵循 ACID 的事務稱為**剛性事務**,而基於 BASE 思想實現的事務稱為**柔性事務**。柔性事務並不是完全放棄了 ACID,僅僅是放寬了一致性要求:事務完成後的一致性嚴格遵循,事務中的一致性可適當放寬。 #### 常見的分散式事務實現方案 分散式事務實現方案從型別上去分剛性事務、柔型事務。剛性事務:通常無業務改造,強一致性,原生支援回滾/隔離性,低併發,適合短事務。柔性事務:有業務改造,最終一致性,實現補償介面,實現資源鎖定介面,高併發,適合長事務。 - 剛性事務:XA 協議(2PC、JTA、JTS)、3PC - 柔型事務:TCC/FMT、Saga(狀態機模式、Aop模式)、本地事務訊息、訊息事務(半訊息)、最多努力通知型事務 ##### 兩階段提交(XA) 與本地事務一樣,分散式事務場景下也可以採用兩階段提交的方案來實現。XA 的全稱是 eXtended Architecture,它是一個分散式事務協議,通過二階段提交協議保證強一致性。 XA 規範中定義了分散式事務處理模型,這個模型中包含四個核心角色: - RM (Resource Managers):資源管理器,提供資料資源的操作、管理介面,保證資料的一致性和完整性。最有代表性的就是資料庫管理系統,當然有的檔案系統、MQ 系統也可以看作 RM。 - TM (Transaction Managers):事務管理器,是一個協調者的角色,協調跨庫事務關聯的所有 RM 的行為。 - AP (Application Program):應用程式,按照業務規則呼叫 RM 介面來完成對業務模型資料的變更,當資料的變更涉及多個 RM 且要保證事務時,AP 就會通過 TM 來定義事務的邊界,TM 負責協調參與事務的各個 RM 一同完成一個全域性事務。 - CRMs (Communication Resource Managers):主要用來進行跨服務的事務的傳播。 ![1](https://tva1.sinaimg.cn/large/007S8ZIlgy1giy3cwjfpyj31400tw439.jpg) XA 協議大概的兩個流程為: 1. 第一階段(prepare):事務管理器向所有本地資源管理器發起請求,詢問是否是 ready 狀態,所有參與者都將本事務能否成功的資訊反饋發給協調者; 2. 第二階段 (commit/rollback):事務管理器根據所有本地資源管理器的反饋,通知所有本地資源管理器,步調一致地在所有分支上提交或者回滾。 XA 協議是如何滿足 ACID 的呢? 原子性和永續性我們就不用說,我們看看隔離性和一致性。 **隔離性** XA 協議中沒有描述如何實現分散式事務的隔離性,但是 XA 協議要求每個資源管理器都要實現本地事務,也就是說基於 XA 協議實現的分散式事務的隔離性是由每個資源管理器本地事務的隔離性來保證的,當一個分散式事務的所有子事務都是隔離的,那麼這個分散式事務天然的就實現了隔離性。 **一致性** 在單機環境下的一致性就是保證當前伺服器資料一致即可。事務執行完畢資料最終一致,不同的隔離級別下事務執行過程的中間狀態不能被別的事務觀察到。 事務執行完畢最終一致這個好保證,但是在RR 隔離級別下不可見一個未提交事務的中間態在分散式情況該如何做到呢?單機上 MySQL 提供了MVCC機制,採用多版本控制來處理,那分散式事務場景也是否也可以提供這樣的機制呢?XA 協議並沒有定義怎麼實現全域性的快照,一個基本思路是用一個集中式或者邏輯上單調遞增的東西來控制生成全域性 Snapshot,每個事務或者每條 SQL 執行時都去獲取一次,從而實現不同隔離級別下的一致性。當然開發的難度還是挺大。 存在的問題: - 同步阻塞:當參與事務者存在佔用公共資源的情況,其中一個佔用了資源,其他事務參與者就只能阻塞等待資源釋放,處於阻塞狀態。 - 單點故障:一旦事務管理器出現故障,整個系統不可用。 - 資料不一致:在階段二,如果事務管理器只發送了部分 commit 訊息,此時網路發生異常,那麼只有部分參與者接收到 commit 訊息,也就是說只有部分參與者提交了事務,使得系統資料不一致。 - 不確定性:當事務管理器傳送 commit 之後,並且此時只有一個參與者收到了 commit,那麼當該參與者與事務管理器同時宕機之後,重新選舉的事務管理器無法確定該條訊息是否提交成功。 總體來說 XA 方案實現簡單,但是帶來的問題如果放在資料一致性要求嚴格的場景是無法保證資料正確性的。另外事務管理器單點會帶來隱患,同步阻塞模型也致使併發能力弱。 ##### TCC 關於 TCC(Try-Confirm-Cancel)的概念,最早是由 Pat Helland 於 2007 年發表的一篇名為《Life beyond Distributed Transactions:an Apostate’s Opinion》的論文提出。 TCC 事務機制相比於上面介紹的 XA,解決了其幾個缺點: 1. 解決了協調者單點,由主業務方發起並完成這個業務活動。業務活動管理器也變成多點,引入叢集。 2. 同步阻塞:引入超時,超時後進行補償,並且不會鎖定整個資源,將資源轉換為業務邏輯形式,粒度變小。 3. 資料一致性,有了補償機制之後,由業務活動管理器控制一致性。 TCC 其實就是採用的補償機制,其核心思想是:針對每個操作,都要註冊一個與其對應的確認和補償(撤銷)操作。TCC 模型完全交由業務實現,每個子業務都需要實現 Try-Confirm-Cancel 三個介面,對業務侵入大,資源鎖定交由業務方。 - Try 階段:嘗試執行,完成所有業務檢查(一致性), 預留必須業務資源(準隔離性)。 - Confirm 階段:確認執行真正執行業務,不作任何業務檢查,只使用 Try 階段預留的業務資源,Confirm 操作滿足冪等性。要求具備冪等設計,Confirm 失敗後需要進行重試。 - Cancel 階段:取消執行,釋放 Try 階段預留的業務資源 Cancel 操作滿足冪等性 Cancel 階段的異常和 Confirm 階段異常處理方案基本上一致。 ![5](https://tva1.sinaimg.cn/large/007S8ZIlgy1giy3cx10mhj30z60qq791.jpg) 一個完整的業務活動由一個主業務服務與若干子業務服務組成: 1. 主業務服務負責發起並完成整個業務活動; 2. 業務服務提供 TCC 型業務操作; 3. 業務活動管理器控制業務活動的一致性,它登記業務活動中的操作,並在業務活動提交時確認所有的TCC 型操作的 Confirm 操作,在業務活動取消時呼叫所有 TCC 型操作的 Cancel 操作。 比如一個轉賬操作: 1. 首先在 Try 階段先把轉賬者的錢包凍結起來。 2. 在 Confirm 階段,呼叫轉賬介面操作轉賬,轉賬成功後解凍。 3. 如果 Confirm 階段成功那麼就轉賬成功,否則執行轉賬失敗確認邏輯。 基於 TCC 實現分散式事務,會將原來只需要一個介面就可以實現的邏輯拆分為 Try、Confirm、Cancel 三個介面,所以程式碼實現複雜度相對較高,需要在業務中寫很多的補償機制程式碼。 TCC將事務提交劃分成兩個階段,Try即為一階段,Confirm 和 Cancel 是二階段並行的兩個分支,二選一。從階段劃分上非常像2PC,我們是否可以說TCC是一種2PC或者2PC變種呢? 對比一下 XA 事務模型,TCC 的兩階段提交與 XA 還是有一些區別: 1. 2PC 的操作物件在於資源層,對於開發人員無感知;而 TCC 的操作在於業務層,具有較高開發成本。 2. 2PC 是一個整體的長事務,也是剛性事務;而 TCC 是一組的本地短事務,是柔性事務。 3. 2PC 的 Prepare (表決階段)進行了操作表決;而 TCC 的 Try 並沒有表決準備,直接兼備資源操作與準備能力。 4. 2PC 是全域性鎖定資源,所有參與者阻塞 互動等待 TM 通知;而 TCC 的資源鎖定在於 Try 操作,業務方可以靈活選擇業務資源的鎖定粒度。 #### 本地訊息表 本地訊息表最初是由eBay架構師Dan Pritchett在一篇解釋 BASE 原理的論文《Base:An Acid Alternative》(https://queue.acm.org/detail.cfm?id=1394128)中提及的,業界目前使用這種方案是比較多的,其核心思想是將分散式事務拆分成本地事務進行處理。 方案通過在事務主動發起方額外新建事務訊息表,事務發起方處理業務和記錄事務訊息在本地事務中完成,輪詢事務訊息表的資料傳送事務訊息,事務被動方基於訊息中介軟體消費事務訊息表中的事務。 基於本地訊息表的方案,每個事務發起方都需要額外新建事務訊息記錄表,用於記錄分散式事務的訊息的發生、處理狀態。 ![3](https://tva1.sinaimg.cn/large/007S8ZIlgy1giy3cxytg1j31n80p6wk0.jpg) 事務發起方在處理完業務邏輯之後需要將當前事務儲存在訊息表中,之後將訊息傳送到訊息中介軟體中,並將訊息的狀態設定為 “傳送中”。 如果訊息在投遞過程中丟失怎麼辦呢?事務發起方可以設定一個定時任務主動掃描狀態為 “傳送中” 的訊息重新投送。只有訊息被業務方消費完畢返回消費成功的結果才確認成功並將訊息狀態改為“已傳送”。 這裡因為網路異常或者傳送異常導致一個訊息可能會被重複傳送,所以要求接收方要做到冪等性,允許重複消費。 這種方案的好處就是方案簡單,成本較低,實現也不復雜。 但是壞處也有很多,比如通過訊息的方式延遲不好控制;本地訊息表與業務耦合在一起沒有做到通用性;本地訊息表基於資料庫來實現,有一定的瓶頸。 #### 事務訊息 上面說的本地訊息表的模式無法支援本地事務執行和訊息傳送一致性的問題,如果能在本地事務執行和發訊息這兩個操作上加上事務,那豈不是完美。 基於這個思路, 在 MQ 中儲存訊息的狀態才是真理,訊息生產者先把訊息傳送給MQ,此時訊息狀態為“待確認”,接著生產者去執行本地事務,如果執行成功就給MQ傳送訊息讓他更改訊息狀態為 “待發送”併發送訊息,如果執行失敗則刪除訊息。 這樣就保證了本地事務和訊息傳送一致性問題。 ![4](https://tva1.sinaimg.cn/large/007S8ZIlgy1giy3csvpllj31di0lcjvz.jpg) 1. 首先事務發起方先往 MQ 傳送一條預讀訊息,這條訊息與普通訊息的區別在於他只對 MQ 可見不會向下傳播。 2. MQ接受到訊息後,先進行持久化,則儲存中會新增一條狀態為`待發送`的訊息,接著給事務發起方返回處理完成的 ACK;事務發起方收到處理完成的 ACK 之後開始執行本地事務。 3. 發起方會根據本地事務的執行狀態來決定這個預讀訊息是應該繼續往前還是回滾。另外 MQ 也應該支援自己反查來解決異常情況,如果發起方本地事務已經執行完畢傳送訊息到MQ,但是訊息因為網路原因丟失,那麼怎麼解決。所以這個反查機制很重要。 4. 本地事務執行成功以後,MQ 也接收到成功通知,接著將訊息狀態更新為可傳送,然後將訊息推送給下游的消費者,這個時候消費者就可以去處理自己的本地事務 。 **注意點**:由於MQ通常都會保證訊息能夠投遞成功,因此,如果業務沒有及時返回ACK結果,那麼就有可能造成MQ的重複訊息投遞問題。**因此,對於訊息最終一致性的方案,訊息的消費者必須要對訊息的消費支援冪等,不能造成同一條訊息的重複消費的情況。** #### SAGA 事務模型 Saga是什麼?Saga的定義是 “長時間活動的事務 ”(Long Lived Transaction,後文簡稱為LLT)。他是普林斯頓大學 HECTOR GARCIA-MOLINA 教授在1987年的一篇關於分散式資料庫的論文中提出來的概念。 Long Lived 從字面意義上不清晰,Long 到底意味著多長?事務持續時間是一個小時、一天甚至一週嗎?其實都不是,時間跨度並不重要。重要的是什麼?關鍵的是跨系統的多次“事務”,Saga 往往由多個外部子事務構成,需要通過多次外部系統的訊息互動,才能將整體事務從開始遷移到結束狀態,這和我們原來常見的在一個數據庫的短事務不一樣。比如一個旅行的訂單,是由機票、旅館、租車三個子訂單構成,都需要外部的確認,缺任何一個步驟,不能成行,這就是一個典型的 LLT。 看起來 Sage 的定義與別的分散式事務沒有什麼不同。分散式事務不就是多個不同的子事務構成一個整體嗎?再來看看 補償機制: 每個本地事務有相應的執行模組和補償模組,當 Sage 事務中的任意一個本地事務出錯, 可以通過呼叫相關事務對應的補償方法恢復,達到事務的最終一致性。 Saga 模型是把一個分散式事務拆分為多個本地事務,每個本地事務都有相應的執行模組和補償模組(對應TCC 中的 Confirm 和 Cancel),當 Saga 事務中任意一個本地事務出錯時,可以通過呼叫相關的補償方法恢復之前的事務,達到事務最終一致性。 由於 Saga 模型中沒有 Prepare 階段,因此事務間不能保證隔離性,當多個 Saga 事務操作同一資源時,就會產生更新丟失、髒資料讀取等問題,這時需要在業務層控制併發,例如: - 在應用層面加鎖; - 應用層面預先凍結資源。 Saga 恢復方式 Saga 支援向前和向後恢復: - 向後恢復:補償所有已完成的事務,如果任一子事務失敗; - 向前恢復:重試失敗的事務,假設每個子事務最終都會成功。 雖然 Saga 和 TCC 都是補償事務,但是由於提交階段不同,所以兩者也是有不同的: - Saga 沒有 Try 行為直接 Commit,所以會留下原始事務操作的痕跡,Cancel 屬於不完美補償,需要考慮對業務上的影響。TCC Cancel 是完美補償的 Rollback,補償操作會徹底清理之前的原始事務操作,使用者是感知不到事務取消之前的狀態資訊的。 - Saga 的補償操作通常可以非同步執行,TCC 的 Cancel 和 Confirm 可以跟進需要是否非同步化。 - Saga 對業務侵入較小,只需要提供一個逆向操作的 Cancel 即可;而 TCC 需要對業務進行全域性性的流程改造。 - TCC 最少通訊次數為 2n,而 Saga 為 n(n=子事務的數量)。 因為也是採用補償機制,那麼必然要求服務保持冪等性,如果服務呼叫超時需要通過冪等性來避免多次請求帶來的問題。 事務特性的滿足: 原子性:Saga 協調器保證整體事務要麼全部執行成功,要麼全部回滾。 一致性:Sage 保證最終一致性。 永續性:Saga 將整體事務拆分成獨立的本地事務,所以永續性在本地事務中很好實現。 但是隔離性 Saga 無法實現,因為大事務被拆分為多個小事務,每個事務提交的時機不同很難保證已提交的小事務不被別人可見。 目前業界提供兩類 Saga 的實現方式: - 一種是集中式協調的實現方式。 集中式協調方式就是通過一個 Saga 物件來追蹤所有的 Saga 子任務的呼叫,由它來管理,追蹤整個事務是否應該提交或補償。 這種方式帶來的缺點就是這種協調方式必然要與第一個Saga 事務耦合,即與業務耦合在一起。 - 一種是分散式實現方式。 分散式協調方式肯定就能避免耦合的問題。分散式實現的方案也很多,比如通過事件機制來實現,一條 Saga 事務鏈上的所有事務都訂閱同一個事件,如果失敗則通過失敗對應的事件訊息來回滾即可。 這種方式帶來的好處肯定是顯而易見的,但是也會有另一個問題,多個事件帶來的肯定是高併發的處理,那麼會不會因為多個事件處理相關的問題帶來一些迴圈依賴的問題。 #### 開源分散式事務框架簡介 ##### Seata Seata(Simple Extensible Autonomous Transaction Architecture,簡單可擴充套件自治事務框架)是 2019 年 1 月份螞蟻金服和阿里巴巴共同開源的分散式事務解決方案。 Seata 會有 4 種分散式事務解決方案,分別是 AT 模式、TCC 模式、Saga 模式和 XA 模式。 ![6](https://tva1.sinaimg.cn/large/007S8ZIlgy1giy3ctu9a9j31a80e2dgy.jpg) **XA 模式** XA 模式是 Seata 將會開源的另一種無侵入的分散式事務解決方案,任何實現了 XA 協議的資料庫都可以作為資源參與到分散式事務中,目前主流資料庫,例如 MySql、Oracle、DB2、Oceanbase 等均支援 XA 協議。 XA 協議有一系列的指令,分別對應一階段和二階段操作。“xa start” 和 “xa end” 用於開啟和結束XA 事務;“xa prepare” 用於預提交 XA 事務,對應一階段準備;“xa commit”和“xa rollback”用於提交、回滾 XA 事務,對應二階段提交和回滾。 在 XA 模式下,每一個 XA 事務都是一個事務參與者。分散式事務開啟之後,首先在一階段執行“xa start”、“業務 SQL”、“xa end”和 “xa prepare” 完成 XA 事務的執行和預提交;二階段如果提交的話就執行 “xa commit”,如果是回滾則執行“xa rollback”。這樣便能保證所有 XA 事務都提交或者都回滾。 ![10](https://tva1.sinaimg.cn/large/007S8ZIlgy1giy3cu5wksj314i0u042c.jpg) XA 模式下,使用者只需關注自己的“業務 SQL”,Seata 框架會自動生成一階段、二階段操作;XA 模式的實現如下: ![11](https://tva1.sinaimg.cn/large/007S8ZIlgy1giy3cxfe7kj316c0u0774.jpg) - 一階段: 在 XA 模式的一階段,Seata 會攔截“業務 SQL”,在“業務 SQL”之前開啟 XA 事務(“xa start”),然後執行“業務 SQL”,結束 XA 事務“xa end”,最後預提交 XA 事務(“xa prepare”),這樣便完成 “業務 SQL”的準備操作。 - 二階段提交: 執行“xa commit”指令,提交 XA 事務,此時“業務 SQL”才算真正的提交至資料庫。 - 二階段回滾: 執行“xa rollback”指令,回滾 XA 事務,完成“業務 SQL”回滾,釋放資料庫鎖資源。 XA 模式下,使用者只需關注“業務 SQL”,Seata 會自動生成一階段、二階段提交和二階段回滾操作。XA 模式和 AT 模式一樣是一種對業務無侵入性的解決方案;但與 AT 模式不同的是,XA 模式將快照資料和行鎖等通過 XA 指令委託給了資料庫來完成,這樣 XA 模式實現更加輕量化。 **AT 模式** AT 模式是一種無侵入的分散式事務解決方案。在 AT 模式下,使用者只需關注自己的“業務 SQL”,使用者的 “業務 SQL” 作為一階段,Seata 框架會自動生成事務的二階段提交和回滾操作。 ![7](https://tva1.sinaimg.cn/large/007S8ZIlgy1giy3cvu2tgj31a60iyacc.jpg) AT 模式的一階段、二階段提交和回滾 均由 Seata 框架自動生成,使用者只需編寫“業務 SQL”,便能輕鬆接入分散式事務,AT 模式是一種對業務無任何侵入的分散式事務解決方案。 **TCC 模式** 2019 年 3 月份,Seata 開源了 TCC 模式,該模式由螞蟻金服貢獻。TCC 模式需要使用者根據自己的業務場景實現 Try、Confirm 和 Cancel 三個操作;事務發起方在一階段 執行 Try 方式,在二階段提交執行 Confirm 方法,二階段回滾執行 Cancel 方法。 ![8](https://tva1.sinaimg.cn/large/007S8ZIlgy1giy3cupwnnj30z20u0gpo.jpg) TCC 三個方法描述: - Try:資源的檢測和預留; - Confirm:執行的業務操作提交;要求 Try 成功 Confirm 一定要能成功; - Cancel:預留資源釋放。 使用者接入 TCC 模式,最重要的事情就是考慮如何將業務模型拆成 2 階段,實現成 TCC 的 3 個方法,並且保證 Try 成功 Confirm 一定能成功。相對於 AT 模式,TCC 模式對業務程式碼有一定的侵入性,但是 TCC 模式無 AT 模式的全域性行鎖,TCC 效能會比 AT 模式高很多。 **Saga 模式** Saga 模式是 Seata 即將開源的長事務解決方案,將由螞蟻金服主要貢獻。在 Saga 模式下,分散式事務內有多個參與者,每一個參與者都是一個衝正補償服務,需要使用者根據業務場景實現其正向操作和逆向回滾操作。 分散式事務執行過程中,依次執行各參與者的正向操作,如果所有正向操作均執行成功,那麼分散式事務提交。如果任何一個正向操作執行失敗,那麼分散式事務會去退回去執行前面各參與者的逆向回滾操作,回滾已提交的參與者,使分散式事務回到初始狀態。 ![9](https://tva1.sinaimg.cn/large/007S8ZIlgy1giy3cyh4mdj30pu0qmjtf.jpg) Saga 模式下分散式事務通常是由事件驅動的,各個參與者之間是非同步執行的,Saga 模式是一種長事務解決方案。 ##### ServiceComb ServiceComb 是華為開源的微服務框架,目前已升級為 Apache 頂級專案。 準確來說它並不是一個純粹的分散式事務框架而是微服務框架,最開始的版本是 Go 語言,後面支援了 Java。 ServiceComb 由 3 個子專案組成: - java-chassis:服務治理 - service-center:服務註冊 - saga:分散式事務解決 從名字上看很顯然是基於 Saga 模式開發的柔性事務方案。Saga系統分為兩部分:Alpha 和 Omega。Alpha 是獨立的服務,扮演事務協調器的作用。Omega 作為開發元件,和業務程序執行在一起。 ![12](https://tva1.sinaimg.cn/large/007S8ZIlgy1giy3cv5finj30n00c4q3g.jpg) Omega 會以切面程式設計的方式嚮應用程式注入相關的處理模組。這裡有攔截請求的模組, 用來幫助我們構建分散式事務呼叫的上下文。 同時在事務處理初始階段處理事務的相關準備的操作,例如建立 Saga 起始事件,以及相關的子起始事件, 根據事務的執行的成功或者失敗生產相關的事務終止或者失敗事件。 Omega 會與 Alpha 進行連結會把這些事件通知給 Alpha。 Alpha 可以在後臺進行分析,根據 Saga 事務執行的情況給 Omega 下達相關的指令進行相關的回滾恢復。 這樣設計的好處是 Saga 實現程式碼與使用者的程式碼分離, 使用者只需要新增幾個 annotation,Saga 實現就能 Saga 事件的執行情況並進行相關的處理。 但是不能忘記的是,軟體開發者做的確實有些不地道,”借鑑“了國外友人的原始碼,卻沒有新增許可宣告。 https://github.com/go-chassis/go-chassis/issues/28 經過網友的筆誅討伐,好在及時浪子回頭,從此在網際網路的書頁上留下了“淡淡的憂傷”。