Seata發展歷史
筆者於2014年開始著手解決阿里巴巴集團內部業務的分散式事務問題,從0到1研發一個支援非侵入模式(內部稱之為AT模式,即自動模式)和TCC模式(內部稱之為MT模式,即手動模式)的分散式事務中介軟體TXC(Taobao Transaction Constructor)。TXC被廣泛應用於阿里巴巴集團內部業務,主要用於解決HSF服務框架下多個數據庫讀寫間的一致性問題。在實際業務使用中,以非侵入模式為主,TCC模式為輔助。
2016年開始,這個產品以雲服務的形式對外輸出,名稱為GTS(Global Transaction Service),服務於眾多大型私有云使用者和公有云使用者。
2019年1月,阿里巴巴中介軟體團隊推出了GTS開源版本 Fescar(Fast & Easy Commit And Rollback),並和開源社群一起共建開源分散式事務解決方案。Fescar的願景是:讓分散式事務的使用像本地事務的使用一樣簡單和高效,並逐步解決開發者們遇到的分散式事務方面的所有難題。
在Fescar開源後,螞蟻金服加入Fescar社群參與共建,隨後Fescar被改名為Seata(Simple Extensible Autonomous Transaction Architecture)。雖然Seata目前已經包含了多種事務模式,但其最吸引客戶的始終是AT模式,因為技術發展趨勢一定是從侵入式到非侵入式,提高研發效率。
Seata已經是Github上一個大熱的專案,開源兩年多截止2021年8月已有兩萬多的“star”數和六千多的“fork”數,專案還在快速迭代中。目前Seata已成為業界主流的分散式事務解決方案。
Seata總體架構
Seata程式碼總量不大,目錄結構比較簡潔。
模組組成
Seata的目錄結構如下圖所示。
各模組的說明如下。
- all:只有一個pom檔案,指定了Seata依賴哪些包。
- bom:只有一個pom檔案,指定了Seata依賴管理的包,即pom檔案的<dependencyManagement>節點的內容。
- changes:描述了版本變更情況。
- common:通用模組。定義了通用的工具類、執行緒工具、異常、載入類等。
- compressor:壓縮模組。定義了多種主流壓縮格式,比如Zip、Gzip、7z、Lz4、Bzip2等,用來實現訊息壓縮功能。
- config:配置模組。用於連線和操作配置中心,支援多種主流配置中心元件,包括Nacos、Apollo、Etcd、Consul、ZooKeeper等。
- core:核心模組。定義了RPC、Netty、事件、協議、事務上下文等。
- discovery:發現模組。用於服務發現,支援多種主流的可用作微服務註冊中心的元件,包括Nacos、Etcd、Eureka、Redis、ZooKeeper等。
- distribution:只有一個pom檔案,用於打包釋出。
- integration:整合模組。整合了Seata對多種RPC框架的支援,包括Dubbo、gRPC、SOFA-RPC等。用來實現Seata事務上下文在RPC框架的傳遞。
- metrics:度量模組。用於收集一些Seata執行指標資料,並匯出到一些監控系統(如使用廣泛的普羅米修斯)中。
- rm:資源管理器模組。定義了多種型別資源管理器(AT模式的資源管理器、TCC模式的資源管理器、Saga模式的資源管理器、XA模式的資源管理器)的公共元件。
- rm-datasource:AT模式的資源管理器模組。實現了AT模式的資料來源代理、SQL語句處理等。該模組也包括對XA模式的支援。
- saga:Saga模式的資源管理器模組。用來實現對Saga模式事務的支援。
- script:指令碼模組。定義了需要的指令碼檔案和配置檔案。
- seata-spring-boot-starter:用於與Spring Boot結合,簡化使用。
- serializer:序列化模組。用於Seata訊息序列化和反序列化,支援多種協議,包括Seata私有序列化協議、FST、Hessian、Kryo等。
- server:服務端模組。用來實現事務協調器,維護全域性事務和分支事務的狀態,推進事務兩階段提交/回滾。
- spring:Spring支援模組。定義了Seata事務註解。
- sqlparser:SQL解析模組。Seata使用Druid SQL直譯器。
- style:定義了程式碼規範。
- tcc:TCC模式資源管理器模組。用來實現對TCC事務模式的支援。
- test:測試模組。
- tm:事務協調器模組。定義了全域性事務的範圍、開啟全域性事務、提交/回滾全域性事務。
邏輯結構
Seata有3個主要角色:TM(Transaction Manager)、RM(Resource Manager)和TC(Transaction Coordinator)。
其中,TM和RM是以SDK的形式作為Seata的客戶端與業務系統整合在一起,TC作為Seata的服務端獨立部署,如下圖所示。
TM:事務管理器。與TC互動,開啟、提交、回滾全域性事務。
RM:資源管理器。與TC互動,負責資源的相關處理,包括分支事務註冊與分支事務狀態上報。
TC:事務協調器。維護全域性事務和分支事務的狀態,推進事務兩階段處理。對於AT模式的分支事務,TM負責事務併發控制。
Seata處理分散式事務的主要流程如下圖所示。
(1)TM開啟全域性事務(TM 向TC 開啟全域性事務)。
(2)事務參與者透過RM與資源互動,並註冊分支事務(RM向TC註冊分支事務)。
(3)事務參與者在完成資源操作後,上報分支事務狀態(RM向TC上報分支事務完成狀態)。
(4)TM結束全域性事務,事務一階段結束(TM向TC提交/回滾全域性事務)。
(5)TC 推進事務二階段操作(TC向RM發起二階段提交/回滾)。
Seata 事務模式
Seata支援4種事務模式:AT、TCC、Saga、XA。本節做一個簡要說明,後面章節會對AT模式和TCC模式進行深入剖析。
AT模式
AT 模式是 Seata 主推的分散式事務解決方案,對業務無侵入,真正做到了業務與事務分離,使用者只需關注自己的“業務 SQL語句”。
AT模式使用起來非常簡單,與完全沒有使用分散式事務方案相比,業務邏輯不需要修改,只需要增加一個事務註解@GlobalTransactional即可,如下圖所示。
TCC模式
TCC 模式需要使用者根據自己的業務場景實現 try()、confirm() 和 cancel()這3個方法:事務發起方在一階段執行try()方法,在二階段提交執行 confirm()方法,在二階段回滾執行cancel()方法。
在TCC模式中,Seata框架把每組TCC服務介面當作一個資源(TCC Resource)。這套TCC服務介面可以是RPC,也可以是服務內JVM呼叫。在業務啟動時,Seata框架會自動掃描並識別出TCC服務介面的釋出方和呼叫方:
對於釋出方,則Seata框架會在業務啟動時向TC註冊TCC Resource。與 AT模式的DataSource Resource 一樣,每個TCC Resource也會帶有一個資源 ID。
對於呼叫方,則Seata 框架會給其加上切面,在執行時該切面會攔截所有對 TCC 服務介面的呼叫。每呼叫一次 try 介面,切面都會先向TC 註冊一個分支事務,然後才去執行try()方法的業務邏輯並向TC彙報分支事務狀態。
在請求鏈路呼叫完成後,發起方通知 TC 提交或回滾分散式事務,進入二階段呼叫流程。此時,TC 會根據之前註冊的分支事務,回撥對應參與者去執行TCC 資源的 confirm() 或 cancel()方法。
Seata TCC 框架本身很簡單,主要是掃描TCC服務介面、註冊資源、攔截介面呼叫、註冊分支事務、彙報分支事務狀態、回撥二階段介面。對於TCC模式來說,最複雜邏輯是TCC服務介面的實現。
使用者以TCC模式接入Seata框架,最重要的是考慮如何將自己的業務模型拆成兩階段來實現。
TCC 模式與AT模式的主要區別如下。
(1)在使用上,TCC 模式依賴使用者自行實現的3個方法(try()、confirm()、cancel())成本較大;AT 模式依賴全域性事務註解和代理資料來源,程式碼基本不需要改動,對業務無侵入、接入成本極低。
(2)TCC 模式的作用範圍在應用層,本質上是實現針對某種業務邏輯的正向和反向方法;AT模式的作用範圍在底層資料來源,透過儲存操作行記錄的前、後鏡像和生成反向SQL語句進行補償操作,對上層應用透明。
(3)TCC模式事務併發控制由業務自行“加鎖”,AT模式由Seata框架自動“加鎖”。
1.舉例
以“扣錢”場景為例,在接入 TCC 模式前,對賬戶“扣錢”,只需一條更新賬戶餘額的 SQL 語句就能完成;但是在接入 TCC 模式之後,使用者則需要考慮如何將原來一步就能完成的“扣錢”操作拆成兩階段,實現成3個方法,並且保證如果一階段try()方法成功則二階段 confirm()方法也一定能成功。
如下圖所示,try()方法在一階段執行,需要做資源的檢查和預留。在“扣錢”場景下,try()方法要做的是檢查賬戶餘額是否充足、預留轉賬資金(預留的方式就是凍結A賬戶的轉賬金額)。在try()方法執行後,賬戶A的餘額雖然還是100元,但是其中有30元已經被凍結了,不能被其他事務使用。
二階段confirm()方法執行真正的“扣錢”操作。confirm()方法會使用try()方法凍結的金額執行賬號“扣錢”。在confirm()方法執行後,賬戶 A 在一階段中凍結的 30 元已經被扣除,賬戶 A 的餘額變為 70 元 。
如果二階段是回滾,則需要在cancel()方法內釋放一階段try()方法凍結的 30 元,使賬戶A回到初始狀態,100元全部可用。
相比AT模式,TCC模式對業務程式碼有很強的侵入性。但是 TCC 模式沒有AT模式的全域性行鎖,“加鎖”邏輯完全需要根據業務特點制定。
在一些場景下,TCC模式的效能會比AT模式的效能更好。但多數場景下,TCC模式業務自己實現的“加鎖”機制效能不會有明顯優勢,反而有較大劣勢。建議用AT模式作為預設方案,用TCC模式作為補充方案。
Saga模式
Saga理論出自Hector和Kenneth 1987發表的論文SAGAS。
Saga是一種補償協議。在 Saga 模式中,在分散式事務內有多個參與者,每一個參與者都是一個衝正補償服務,需要使用者根據業務場景實現其正向操作和逆向回滾操作。
如下圖所示,T1~T3都是正向的業務流程,都對應著一個衝正逆向操作C1~C3。
在分散式事務執行過程中,會依次執行各參與者的正向操作。
如果所有正向操作均執行成功,則分散式事務提交。
如果任何一個正向操作執行失敗,則分散式事務會退回去執行前面各參與者的逆向回滾操作,回滾已提交的參與者,使分散式事務回到初始狀態。
Saga 模式的正向服務與補償服務也需要業務開發者實現,因此也具有很強的業務侵入性。在Saga 模式中,分散式事務通常是由事件驅動的,在各個參與者之間是非同步執行的。
Saga 模式是一種長事務解決方案,適用於業務流程長且需要保證事務最終一致性的業務系統。Saga 模式的一階段就會提交本地事務,在無鎖、長流程情況下這可以保證效能。
Saga模式的優勢:
在一階段提交本地資料庫事務,無鎖,高效能。
參與者可以採用事件驅動非同步執行,高吞吐。
補償服務即正向服務的“反向”操作,易於理解,易於實現。
Saga模式也存在很明顯的缺點:在一階段已經提交了本地資料庫事務,且沒有進行“預留”動作,所以不能保證隔離性,不容易進行併發控制。與AT模式和TCC模式相比,Saga 模式的適用場景有限。
XA模式
在XA模式中,需要在Seata定義的分散式事務範圍內,利用事務資源(資料庫、訊息服務等)實現對XA協議的支援,以XA協議的機制來管理分支事務。
本質上,Seata另外的3大事務模式(AT、TCC、Saga)都是補償型的。事務處理機制構建在框架或應用中。事務資源本身對分散式事務是無感知的。
而在XA模式下,事務資源對分散式事務是可感知的。
XA協議要求事務資源本身提供對規範和協議的支援。因為事務資源(資料庫、訊息佇列)可感知並參與分散式事務處理過程,所以事務資源可以保障從任意視角對資料的訪問進行有效隔離,滿足全域性資料一致性。
XA模式是傳統的分散式強一致性的解決方案,效能較低,在實際業務中使用得較少,本書不做深入探討。
*本文節選自
《正本清源分散式事務之Seata(全綵)》一書
Seata作者編寫,分散式事務處理
歡迎閱讀本書瞭解更多精彩內容!