分散式事務是分散式系統中非常重要的一部分。假設一個使用者購買商品的業務邏輯,系統有3個微服務組成,分別是訂單服務、賬戶服務、庫存服務,使用者在提交訂單後會從使用者賬戶餘額中扣款,同時扣減庫存數量。在這樣的場景下扣款和減庫存需要事務一致性保證。就可能會使用到分散式事務解決方案。
分散式事務的實現可以採用不同的技術和協議,例如兩階段提交(2PC)、三階段提交(3PC)、基於訊息佇列的事務等。這些方法和協議都致力於確保在分散式環境下的事務狀態的一致性和可靠性。
一、分散式事務開源元件Seata
在分散式事務開源元件和解決方案中,最廣泛應用的是螞蟻金服開源的 Seata。Seata 是一個開源的分散式事務解決方案,在微服務架構下提供高效能、易用的分散式事務服務。在Seata開源之前,其內部版本一直扮演著阿里巴巴集團應用架構層資料一致性的中介軟體角色,幫助經濟順利度過過去一年的雙11,為上層業務提供了強大的技術支撐。經過多年的發展,其商用產品已在阿里雲和金融雲上銷售。2019.1 為了打造更完善的技術生態和包容性的技術成果,Seata正式宣佈對外開源。
1.1、Seata分散式事務架構
Seata的設計思想是將一個分散式事務拆分為包含多個分支事務(Branch Transaction)的全域性事務(Global Transaction)。每個分支事務表示一個本地事務,具備ACID特性。全域性事務的責任是協調管理其下屬的分支事務,以實現統一的一致性。要麼一起成功提交,要麼一起回滾。
Seata事務管理中有三個重要的角色:
- TC(Transaction Coordinator)-事務協調者:維護全域性和分支事務的狀態,協調全域性事務提交或回滾。
- TM(Transaction Manager)-事務管理器:定義全域性事務的範圍、開始全域性事務、提交或回滾全域性事務。
- RM(Resource Manager)-資源管理器:管理分支事務處理的資源,與TC交談以註冊分支事務和報告分支事務的狀態,並驅動分支事務提交或回滾。
TM會首先註冊全域性事務,之後業務呼叫各個微服務,由各自的RM向TC發起分支事務的註冊,之後執行各個分支事務的sql,執行完畢之後RM會向TC報告分支事務的狀態,所有分支事務執行完畢之後,TM向TC發起提交或回滾全域性事務,此時TC會檢查分支事務的狀態來決定是提交還是回滾傳送給RM。
以上只是Seata分散式事務的基本模型。
1.2、分散式事務模型
解決分散式事務,各個子系統之間必須能感知到彼此的事務狀態,才能保證狀態一致,因此需要一個事務協調者來協調每一個事務的參與者(子系統事務)。這裡的子系統事務,稱為分支事務;有關聯的各個分支事務在一起稱為全域性事務.
名詞解析:
全域性事務:整個分散式事務
分支事務:分散式事務中包含的每個子系統的事務
最終一致性:各分支事務分別執行並提交,如果有不一致的情況,想辦法補償恢復,達到資料的最終一致性
強一致性:各事務執行完業務不要提交,等待彼此結束,之後統一提交或回滾
二、分散式事務XA、AT、TCC、SAGA模式
Seata提供了XA、AT、TCC、SAGA四種不同的分散式事務解決方案:
(1)XA模式:強一致性分階段事務模式,犧牲了一定的可用性,無業務侵入。
(2)TCC模式:最終一致的分階段事務模式,有業務侵入。
(3)AT模式:最終一致的分階段事務模式,無業務侵入,也是Seata的預設模式。
(4)SAGA模式:長事務模式,有業務侵入。
2.1、XA模式
XA規範是X/Open組織定義的分散式事務處理(DTP,Distributed Transaction Processing)標準,XA規範描述了全域性的TM與區域性的RM之間的介面,幾乎所有主流的資料庫都對XA規範提供了支援。
標準的XA模式為兩階段提交:
第一階段由事務協調者向RM(XA模式下一般由資料庫實現)發起事務準備請求,RM執行完畢之後,並不直接提交事務,而是將執行的結果告知事務協調者。
第二階段由事務協調者判斷RM的返回結果,如果分支事務都成功了,向RM發起提交請求,RM執行事務提交併返回已提交請求。
但是,如果在事務執行過程中有一個失敗了,事務協調者則會回滾所有已執行事務。
Seata在實現XA模式時進行了一定的調整,但大體上相似:
RM一階段工作:
- 註冊分支事務到TC
- 執行分支業務SQL但不提交
- 報告執行狀態到TC
TC二階段工作:
- TC檢測各分支事務執行狀態
- 如果都成功,通知所有RM提交事務
- 如果有失敗,通知所有RM回滾事務
RM二階段工作:
- 接受TC指令,提交或回滾事務
2.1.1、XA模式總結
優點:
- 事務強一致性,滿足ACID原則
- 常用資料庫都支援,實現簡單,沒有程式碼侵入
缺點:
- 因為一階段需要鎖定資料庫資源,等待二階段結束才釋放,所以效能較差
- 依賴關係型資料庫實現事務
2.2、AT模式
AT模式同樣是分階段提交的事務模型,不過缺彌補了XA模型中資源鎖定週期過長的缺陷。
AT模式在執行完sql之後會直接提交事務,而不是進行等待,在執行的同時RM攔截本次執行,記錄更新前後的快照到資料庫的undo_log中。與XA的不同之處在於階段一RM的工作:
- 註冊分支事務
- 記錄undo-log(資料快照)
- 執行業務sql並提交
- 報告事務狀態
階段二提交時RM的工作:
- 刪除undo-log即可
階段二回滾時RM的工作:
- 根據undo-log回覆資料到更新前
具體案例:例如,一個分支業務的SQL是這樣的:update tb_account set money = money - 10 where id = 1
如果這條sql執行成功,那麼money欄位自然是90,如果執行失敗,則根據資料快照恢復資料。
AT工作模型
2.2.1、AT模式總結
Seata AT模式是一種非侵入式分散式事務解決方案。Seata 在內部實現了一個用於資料庫操作的代理層。在使用 Seata AT 模式時,我們實際上使用的是 Seata 提供的內建資料來源代理 DataSourceProxy。Seata 在此代理層中新增了很多邏輯,例如插入回滾undo_log記錄和檢查全域性鎖。
為什麼要檢查全域性鎖?這是因為 Seata AT 模式的事務隔離是基於支援事務的本地隔離級別。在資料庫本地隔離級別為讀取提交或以上的前提下,Seata 設計了一個由事務協調器維護的全域性寫獨佔鎖,以保證事務之間的寫入隔離。同時,預設情況下,全域性事務在讀取未提交隔離級別定義。
與XA模式最大的區別是:
- XA模式一階段不提交事務,鎖定資源;AT模式一階段直接提交,不鎖定資源。
- XA模式依賴資料庫機制實現回滾;AT模式利用資料快照實現資料回滾。
- XA模式強一致;AT模式最終一致
優點:
- 一階段完成直接提交事務,釋放資料庫資源,效能比較好
- 利用全域性鎖實現讀寫隔離
- 沒有程式碼侵入,框架自動完成回滾和提交
缺點:
- 兩階段之間屬於軟狀態,屬於最終一致
- 框架的快照功能會影響效能,但比XA模式要好很多
2.3、TCC模式
TCC模式與AT模式非常相似,每階段都是獨立事務,不同的是TCC透過人工編碼來實現資料恢復。需要實現三個方法:
- Try:資源的檢測和預留;
- Confirm:完成資源操作業務;要求Try成功Confirm一定要能成功。
- Cancel:預留資源釋放,可以理解為Try的反向操作。
舉例,一個扣減使用者餘額的業務。假設賬戶A原來餘額是100,需要餘額扣減30元。
- 階段一(Try): 檢查餘額是否充足,如果充足則凍結金額增加30元,可用餘額扣除30
- 階段二:假如要提交(Confirm),則凍結金額扣減30
- 階段三:如果要回滾(Cancel),則凍結金額扣減30,可用餘額增加30
TCC工作模型圖:
TCC是一種侵入式分散式事務解決方案。這三項操作都需要由業務系統本身實現,這對業務系統有重大影響。設計相對複雜,但優點是TCC不依賴資料庫。它可以跨資料庫和應用程式管理資源,並可以透過侵入式編碼實現不同資料訪問的原子操作,更好地解決各種複雜業務場景中的分散式事務問題。
2.3.1、TCC模式總結
TCC模式的每個階段是做什麼的?
- Try:資源檢查和預留
- Confirm:業務執行和提交
- Cancel:預留資源的釋放
TCC的優點是什麼?
- 一階段完成直接提交事務,釋放資料庫資源,效能好
- 相比AT模型,無需生成快照,無需使用全域性鎖,效能最強
- 不依賴資料庫事務,而是依賴補償操作,可以用於非事務型資料庫
TCC的缺點是什麼?
- 有程式碼侵入,需要人為編寫try、Confirm和Cancel介面
- 軟狀態,事務是最終一致
- 需要考慮Confirm和Cancel的失敗情況,做好冪等處理
2.4、SAGA模式
Saga模式是SEATA提供的長事務解決方案。也分為兩個階段:
- 一階段:直接提交本地事務(TCC是預留)
- 二階段:成功則什麼都不做;失敗則透過編寫補償業務來回滾
Saga模式優點:
- 事務參與者可以基於事件驅動實現非同步呼叫,吞吐高
- 一階段直接提交事務,無鎖,效能好
- 不用編寫TCC中的三個階段,實現簡單
缺點:
- 軟狀態持續時間不確定,時效性差
- 沒有鎖,沒有事務隔離,會有髒寫
SAGA模式下,事務一旦有一個出現問題,則反向按照事務呼叫順序進行補償,從而保證一致性。
三、分散式事務模型對比總結
XA |
AT |
TCC |
SAGA |
|
一致性 |
強一致 |
弱一致 |
弱一致 |
最終一致 |
隔離性 |
完全隔離 |
基於全域性鎖隔離 |
基於資源預留隔離 |
無隔離 |
程式碼侵入 |
無 |
無 |
有,需要編寫3個介面程式碼 |
有,需要編寫狀態機和補償業務 |
效能 |
差 |
好 |
非常好 |
非常好 |
場景 |
對一致性、隔離性有高要求的業務 |
基於關係型資料庫的大多數分散式事務場景都可以 |
對效能要求較高的事務;有非關係型資料庫要參與的事務 |
業務流程長、業務流程多;參與者包含其它公司或遺留系統服務,無法提供TCC模式要求的三個介面 |
總結:
Seata分散式事務框架提供的這四種模式適用於不同應用場景,XA和AT是基於資料庫層面的分散式事務,TCC和SAGA是基於業務層面的分散式事務,資料庫層面事務回滾依賴的是undo sql指令碼,業務層面事務回滾依賴的是自己寫補償程式碼,使用者在選擇分散式事務模式時需要兼併考慮程式碼的侵入性和長事務效能問題。目前看,XA事務模型由於其效能最差,實際專案用的很少了;AT事務模型無程式碼侵入,效能較好,在交易類業務系統(比如:ERP、MES、CRM等)中推薦使用;TCC事務模型雖然效能最好,但需要寫程式碼,且需要結合業務設計,非高併發專案謹慎使用;SAGA模型最複雜,沒有特殊需求,不推薦使用。
參考:
https://seata.apache.org/blog
http://www.yunchengxc.com/