深入解讀分布式事務Seata的XA模式
Seata
Seata 1.2.0 版本重磅發(fā)布新的事務模式:XA 模式,實現(xiàn)對 XA 協(xié)議的支持。
這里,我們從三個方面來深入解讀這個新的特性:
1、是什么(What):XA 模式是什么?
2、為什么(Why):為什么支持 XA?
3、怎么做(How):XA 模式是如何實現(xiàn)的,以及怎樣使用?
1.XA 模式是什么?
這里有兩個基本的前置概念:
1、什么是 XA?
2、什么是 Seata 定義的所謂 事務模式?
基于這兩點,再來理解 XA 模式就很自然了。
1.1 什么是 XA?
XA 規(guī)范 是 X/Open 組織定義的分布式事務處理(DTP,Distributed Transaction Processing)標準。
XA 規(guī)范 描述了全局的事務管理器與局部的資源管理器之間的接口。XA規(guī)范 的目的是允許的多個資源(如數(shù)據(jù)庫,應用服務器,消息隊列等)在同一事務中訪問,這樣可以使 ACID 屬性跨越應用程序而保持有效。
XA 規(guī)范 使用兩階段提交(2PC,Two-Phase Commit)來保證所有資源同時提交或回滾任何特定的事務。
XA 規(guī)范 在上世紀 90 年代初就被提出。目前,幾乎所有主流的數(shù)據(jù)庫都對 XA 規(guī)范 提供了支持。
1.2 什么是 Seata 的事務模式?
Seata 定義了全局事務的框架。
全局事務
定義為若干 分支事務 的整體協(xié)調:
1、TM 向 TC 請求發(fā)起(Begin)、提交(Commit)、回滾(Rollback)全局事務。
2、TM 把代表全局事務的 XID 綁定到分支事務上。
3、RM 向 TC 注冊,把分支事務關聯(lián)到 XID 代表的全局事務中。
4、RM 把分支事務的執(zhí)行結果上報給 TC。(可選)
5、TC 發(fā)送分支提交(Branch Commit)或分支回滾(Branch Rollback)命令給 RM。
Seata 的 全局事務 處理過程,分為兩個階段:
1、執(zhí)行階段 :執(zhí)行 分支事務,并 保證 執(zhí)行結果滿足是 可回滾的(Rollbackable) 和 持久化的(Durable)。
2、完成階段: 根據(jù) 執(zhí)行階段 結果形成的決議,應用通過 TM 發(fā)出的全局提交或回滾的請求給 TC,TC 命令 RM 驅動 分支事務 進行 Commit 或 Rollback。
事務模式
Seata 的所謂 事務模式 是指:運行在 Seata 全局事務框架下的 分支事務 的行為模式。準確地講,應該叫作 分支事務模式。
不同的 事務模式 區(qū)別在于 分支事務 使用不同的方式達到全局事務兩個階段的目標。
即,回答以下兩個問題:
1、執(zhí)行階段 :如何執(zhí)行并 保證 執(zhí)行結果滿足是 可回滾的(Rollbackable) 和 持久化的(Durable)。
2、完成階段: 收到 TC 的命令后,如何做到分支的提交或回滾?
以我們 Seata 的 AT 模式和 TCC 模式為例來理解:
AT 模式
- 執(zhí)行階段: 可回滾:根據(jù) SQL 解析結果,記錄回滾日志 持久化:回滾日志和業(yè)務 SQL 在同一個本地事務中提交到數(shù)據(jù)庫
- 完成階段: 分支提交:異步刪除回滾日志記錄 分支回滾:依據(jù)回滾日志進行反向補償更新
TCC 模式
- 執(zhí)行階段 調用業(yè)務定義的 Try 方法(完全由業(yè)務層面保證 可回滾 和 持久化)
- 完成階段: 分支提交:調用各事務分支定義的 Confirm 方法 分支回滾:調用各事務分支定義的 Cancel 方法
1.3 什么是 Seata 的 XA 模式?
XA 模式: 在 Seata 定義的分布式事務框架內,利用事務資源(數(shù)據(jù)庫、消息服務等)對 XA 協(xié)議的支持,以 XA 協(xié)議的機制來管理分支事務的一種 事務模式。
執(zhí)行階段:
- 可回滾:業(yè)務 SQL 操作放在 XA 分支中進行,由資源對 XA 協(xié)議的支持來保證 可回滾
- 持久化:XA 分支完成后,執(zhí)行 XA prepare,同樣,由資源對 XA 協(xié)議的支持來保證 持久化(即,之后任何意外都不會造成無法回滾的情況)
完成階段:
- 分支提交:執(zhí)行 XA 分支的 commit
- 分支回滾:執(zhí)行 XA 分支的 rollback2. 為什么支持 XA?
2.為什么支持 XA ?
為什么要在 Seata 中增加 XA 模式呢?支持 XA 的意義在哪里呢?
2.1 補償型事務模式的問題
本質上,Seata 已經支持的 3 大事務模式:AT、TCC、Saga 都是 補償型 的。
補償型 事務處理機制構建在 事務資源 之上(要么在中間件層面,要么在應用層面),事務資源 本身對分布式事務是無感知的。
事務資源 對分布式事務的無感知存在一個根本性的問題:無法做到真正的 全局一致性 。
比如,一條庫存記錄,處在 補償型 事務處理過程中,由 100 扣減為 50。此時,倉庫管理員連接數(shù)據(jù)庫,查詢統(tǒng)計庫存,就看到當前的 50。之后,事務因為異外回滾,庫存會被補償回滾為 100。顯然,倉庫管理員查詢統(tǒng)計到的 50 就是 臟 數(shù)據(jù)。
可以看到,補償型 分布式事務機制因為不要求 事務資源 本身(如數(shù)據(jù)庫)的機制參與,所以無法保證從事務框架之外的全局視角的數(shù)據(jù)一致性。
2.2 XA 的價值
與 補償型 不同,XA 協(xié)議 要求 事務資源 本身提供對規(guī)范和協(xié)議的支持。
因為 事務資源 感知并參與分布式事務處理過程,所以 事務資源(如數(shù)據(jù)庫)可以保障從任意視角對數(shù)據(jù)的訪問有效隔離,滿足全局數(shù)據(jù)一致性。
比如,上一節(jié)提到的庫存更新場景,XA 事務處理過程中,中間態(tài)數(shù)據(jù)庫存 50 由數(shù)據(jù)庫本身保證,是不會倉庫管理員的查詢統(tǒng)計 看 到的。(當然隔離級別需要 讀已提交 以上)
除了 全局一致性 這個根本性的價值外,支持 XA 還有如下幾個方面的好處:
1、業(yè)務無侵入:和 AT 一樣,XA 模式將是業(yè)務無侵入的,不給應用設計和開發(fā)帶來額外負擔。
2、數(shù)據(jù)庫的支持廣泛:XA 協(xié)議被主流關系型數(shù)據(jù)庫廣泛支持,不需要額外的適配即可使用。
3、多語言支持容易:因為不涉及 SQL 解析,XA 模式對 Seata 的 RM 的要求比較少,為不同語言開發(fā) SDK 較之 AT 模式將更 薄,更容易。
4、傳統(tǒng)基于 XA 應用的遷移:傳統(tǒng)的,基于 XA 協(xié)議的應用,遷移到 Seata 平臺,使用 XA 模式將更平滑。
2.3 XA 廣泛被質疑的問題
不存在某一種分布式事務機制可以完美適應所有場景,滿足所有需求。
XA 規(guī)范早在上世紀 90 年代初就被提出,用以解決分布式事務處理這個領域的問題。
現(xiàn)在,無論 AT 模式、TCC 模式還是 Saga 模式,這些模式的提出,本質上都源自 XA 規(guī)范對某些場景需求的無法滿足。
XA 規(guī)范定義的分布式事務處理機制存在一些被廣泛質疑的問題,針對這些問題,我們是如何思考的呢?
1、 數(shù)據(jù)鎖定:數(shù)據(jù)在整個事務處理過程結束前,都被鎖定,讀寫都按隔離級別的定義約束起來。
思考: 數(shù)據(jù)鎖定是獲得更高隔離性和全局一致性所要付出的代價。 補償型 的事務處理機制,在 執(zhí)行階段 即完成分支(本地)事務的提交,(資源層面)不鎖定數(shù)據(jù)。而這是以犧牲 隔離性 為代價的。 另外,AT 模式使用 全局鎖 保障基本的 寫隔離,實際上也是鎖定數(shù)據(jù)的,只不過鎖在 TC 側集中管理,解鎖效率高且沒有阻塞的問題。
2、協(xié)議阻塞:XA prepare 后,分支事務進入阻塞階段,收到 XA commit 或 XA rollback 前必須阻塞等待。
思考: 協(xié)議的阻塞機制本身并不是問題,關鍵問題在于 協(xié)議阻塞 遇上 數(shù)據(jù)鎖定。 如果一個參與全局事務的資源 “失聯(lián)” 了(收不到分支事務結束的命令),那么它鎖定的數(shù)據(jù),將一直被鎖定。進而,甚至可能因此產生死鎖。 這是 XA 協(xié)議的核心痛點,也是 Seata 引入 XA 模式要重點解決的問題。 基本思路是兩個方面:避免 “失聯(lián)” 和 增加 “自解鎖” 機制。(這里涉及非常多技術細節(jié),暫時不展開,在后續(xù) XA 模式演進過程中,會專門拿出來討論)
3、 性能差:性能的損耗主要來自兩個方面:一方面,事務協(xié)調過程,增加單個事務的 RT;另一方面,并發(fā)事務數(shù)據(jù)的鎖沖突,降低吞吐。
思考: 和不使用分布式事務支持的運行場景比較,性能肯定是下降的,這點毫無疑問。 本質上,事務(無論是本地事務還是分布式事務)機制就是拿部分 性能的犧牲 ,換來 編程模型的簡單 。 與同為 業(yè)務無侵入 的 AT 模式比較: 首先,因為同樣運行在 Seata 定義的分布式事務框架下,XA 模式并沒有產生更多事務協(xié)調的通信開銷。
其次,并發(fā)事務間,如果數(shù)據(jù)存在熱點,產生鎖沖突,這種情況,在 AT 模式(默認使用全局鎖)下同樣存在的。 所以,在影響性能的兩個主要方面,XA 模式并不比 AT 模式有非常明顯的劣勢。 AT 模式性能優(yōu)勢主要在于:集中管理全局數(shù)據(jù)鎖,鎖的釋放不需要 RM 參與,釋放鎖非???;另外,全局提交的事務,完成階段 異步化。
3.XA 模式如何實現(xiàn)以及怎樣用?
3.1 XA 模式的設計
3.1.1 設計目標
XA 模式的基本設計目標,兩個主要方面:
1、從場景 上,滿足 全局一致性 的需求。
2、從應用上,保持與 AT 模式一致的無侵入。
3、從機制 上,適應分布式微服務架構的特點。
整體思路:
1、與 AT 模式相同的:以應用程序中 本地事務 的粒度,構建到 XA 模式的 分支事務。
2、通過數(shù)據(jù)源代理,在應用程序本地事務范圍外,在框架層面包裝 XA 協(xié)議的交互機制,把 XA 編程模型 透明化。
3、把 XA 的 2PC 拆開,在分支事務 執(zhí)行階段 的末尾就進行 XA prepare,把 XA 協(xié)議完美融合到 Seata 的事務框架,減少一輪 RPC 交互。
3.1.2 核心設計
整體運行機制
XA 模式 運行在 Seata 定義的事務框架內:
- 執(zhí)行階段(E xecute): XA start/XA end/XA prepare + SQL + 注冊分支
- 完成階段(F inish): XA commit/XA rollback
數(shù)據(jù)源代理
XA 模式需要 XAConnection。
獲取 XAConnection 兩種方式:
- 方式一:要求開發(fā)者配置 XADataSource
- 方式二:根據(jù)開發(fā)者的普通 DataSource 來創(chuàng)建
第一種方式,給開發(fā)者增加了認知負擔,需要為 XA 模式專門去學習和使用 XA 數(shù)據(jù)源,與 透明化 XA 編程模型的設計目標相違背。
第二種方式,對開發(fā)者比較友好,和 AT 模式使用一樣,開發(fā)者完全不必關心 XA 層面的任何問題,保持本地編程模型即可。
我們優(yōu)先設計實現(xiàn)第二種方式:數(shù)據(jù)源代理根據(jù)普通數(shù)據(jù)源中獲取的普通 JDBC 連接創(chuàng)建出相應的 XAConnection。
類比 AT 模式的數(shù)據(jù)源代理機制,如下:
但是,第二種方法有局限:無法保證兼容的正確性。
實際上,這種方法是在做數(shù)據(jù)庫驅動程序要做的事情。不同的廠商、不同版本的數(shù)據(jù)庫驅動實現(xiàn)機制是廠商私有的,我們只能保證在充分測試過的驅動程序上是正確的,開發(fā)者使用的驅動程序版本差異很可能造成機制的失效。
這點在 Oracle 上體現(xiàn)非常明顯。參見 Druid issue: https://github.com/alibaba/druid/issues/3707
綜合考慮,XA 模式的數(shù)據(jù)源代理設計需要同時支持第一種方式:基于 XA 數(shù)據(jù)源進行代理。
類比 AT 模式的數(shù)據(jù)源代理機制,如下:
分支注冊
XA start 需要 Xid 參數(shù)。
這個 Xid 需要和 Seata 全局事務的 XID 和 BranchId 關聯(lián)起來,以便由 TC 驅動 XA 分支的提交或回滾。
目前 Seata 的 BranchId 是在分支注冊過程,由 TC 統(tǒng)一生成的,所以 XA 模式分支注冊的時機需要在 XA start 之前。
將來一個可能的優(yōu)化方向:
把分支注冊盡量延后。類似 AT 模式在本地事務提交之前才注冊分支,避免分支執(zhí)行失敗情況下,沒有意義的分支注冊。
這個優(yōu)化方向需要 BranchId 生成機制的變化來配合。BranchId 不通過分支注冊過程生成,而是生成后再帶著 BranchId 去注冊分支。
小結
這里只通過幾個重要的核心設計,說明 XA 模式的基本工作機制。
此外,還有包括 連接保持、異常處理 等重要方面,有興趣可以從項目代碼中進一步了解。
以后會陸續(xù)寫出來和大家交流。
3.1.3 演進規(guī)劃 XA 模式總體的演進規(guī)劃如下:
第 1 步(已經完成):首個版本(1.2.0),把 XA 模式原型機制跑通。確保只增加,不修改,不給其他模式引入的新問題。
第 2 步(計劃 5 月完成):與 AT 模式必要的融合、重構。
第 3 步(計劃 7 月完成):完善異常處理機制,進行上生產所必需的打磨。
第 4 步(計劃 8 月完成):性能優(yōu)化。
第 5 步(計劃 2020 年內完成):結合 Seata 項目正在進行的面向云原生的 Transaction Mesh 設計,打造云原生能力。
3.2 XA 模式的使用
從編程模型上,XA 模式與 AT 模式保持完全一致。
可以參考 Seata 官網(wǎng)的樣例:seata-xa https://github.com/seata/seata-samples/tree/master/seata-xa
樣例場景是 Seata 經典的,涉及庫存、訂單、賬戶 3 個微服務的商品訂購業(yè)務。
在樣例中,上層編程模型與 AT 模式完全相同。只需要修改數(shù)據(jù)源代理,即可實現(xiàn) XA 模式與 AT 模式之間的切換。
@Bean(“dataSourceProxy”) public DataSource dataSource(DruidDataSource druidDataSource) { // DataSourceProxy for AT mode // return new DataSourceProxy(druidDataSource); // DataSourceProxyXA for XA mode return new DataSourceProxyXA(druidDataSource); }
總結
在當前的技術發(fā)展階段,不存一個分布式事務處理機制可以完美滿足所有場景的需求。
一致性、可靠性、易用性、性能等諸多方面的系統(tǒng)設計約束,需要用不同的事務處理機制去滿足。
Seata 項目最核心的價值在于:構建一個全面解決分布式事務問題的 標準化 平臺。 基于 Seata,上層應用架構可以根據(jù)實際場景的需求,靈活選擇合適的分布式事務解決方案。
XA 模式的加入,補齊了 Seata 在 全局一致性 場景下的缺口,形成 AT、TCC、Saga、XA 四大 事務模式 的版圖,基本可以滿足所有場景的分布式事務處理訴求。
當然 XA 模式和 Seata 項目本身都還不盡完美,有很多需要改進和完善的地方。非常歡迎大家參與到項目的建設中,共同打造一個標準化的分布式事務平臺。
到此這篇關于深入解讀分布式事務Seata的XA模式的文章就介紹到這了,更多相關Seata的XA模式內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
jvm之java類加載機制和類加載器(ClassLoader)的用法
這篇文章主要介紹了jvm之java類加載機制和類加載器(ClassLoader)的用法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09SpringBoot使用過濾器、攔截器和監(jiān)聽器的案例代碼(Springboot搭建java項目)
這篇文章主要介紹了SpringBoot使用過濾器、攔截器和監(jiān)聽器(Springboot搭建java項目),本文是基于Springboot搭建java項目,結合案例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-02-02Java Spring WEB應用實例化如何實現(xiàn)
這篇文章主要介紹了Java Spring WEB應用實例化如何實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-12-12java web將數(shù)據(jù)導出為Excel格式文件代碼片段
這篇文章主要為大家詳細介紹了java web將數(shù)據(jù)導出為Excel格式文件代碼片段,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-01-01