一文了解Seata的實(shí)現(xiàn)原理
一、背景
大型廠商根據(jù)分布式事務(wù)實(shí)現(xiàn)規(guī)范,實(shí)現(xiàn)了不同的分布式框架,以簡(jiǎn)化業(yè)務(wù)開(kāi)發(fā)者處理分布式事務(wù)相關(guān)工作,讓開(kāi)發(fā)者專注于核心業(yè)務(wù)開(kāi)發(fā)。
Seata就是這么一個(gè)分布式事務(wù)處理框架,Seata是由阿里開(kāi)源,前身為Fescar,經(jīng)過(guò)品牌升級(jí)變身Seata。
二、分布式事務(wù)規(guī)范
2.1、分布式事務(wù)相關(guān)概念
事務(wù):一個(gè)程序執(zhí)行單元,是用戶定義的一組操作序列,需要滿足ACID屬性。
本地事務(wù):事務(wù)由本地資源管理器管理。
分布式事務(wù):事務(wù)的操作位于不同的節(jié)點(diǎn)。
分支事務(wù):在分布式事務(wù)中,由資源管理器管理的本地事務(wù)。
全局事務(wù):一次性操作多個(gè)資源管理器完成的事務(wù),由一組分支事務(wù)組成。
2.2、分布式事務(wù)實(shí)現(xiàn)規(guī)范
對(duì)于本地事務(wù),可以借助DBMS系統(tǒng)來(lái)實(shí)現(xiàn)事務(wù)的管理,但是對(duì)于分布式事務(wù),它就無(wú)能為力了。對(duì)于分布式事務(wù),目前主要有2種思路:XA協(xié)議的強(qiáng)一致規(guī)范以及柔性事務(wù)的最終一致性規(guī)范。
2.2.1、XA
XA是基于2階段提交協(xié)議設(shè)計(jì)的接口標(biāo)準(zhǔn),實(shí)現(xiàn)了XA規(guī)范的資源管理器就可以參與XA全局事務(wù)。應(yīng)用承擔(dān)事務(wù)管理器TM工作,數(shù)據(jù)庫(kù)承擔(dān)資源管理器RM工作,TM生成全局事務(wù)id,控制RM的提交和回滾。
2.2.2、柔性事務(wù)的最終一致性
該規(guī)范主要有3種實(shí)現(xiàn)方式,TCC、MQ事務(wù)消息、本地消息表。(還存在其他一些不常用實(shí)現(xiàn)方式如Saga)。
TCC:try/confirm/cancel,在try階段鎖定資源,confirm階段進(jìn)行提交,資源鎖定失敗執(zhí)行cancel階段釋放資源。
MQ事務(wù)消息:前提消息系統(tǒng)需要支持事務(wù)如RocketMQ,在本地事務(wù)執(zhí)行前,發(fā)送事務(wù)消息prepare,本地事務(wù)執(zhí)行成功,發(fā)送事務(wù)消息commit,實(shí)現(xiàn)分布式事務(wù)最終一致性。如果事務(wù)消息commit失敗,RocketMQ會(huì)回查消息發(fā)送者確保消息正常提交,如果步驟5執(zhí)行失敗,進(jìn)行重試,達(dá)到最終一致性。
本地消息表:跟MQ事務(wù)消息類似,區(qū)別在于MQ不支持事務(wù)消息,需要借助本地?cái)?shù)據(jù)庫(kù)的事務(wù)管理能力。在步驟1中將需要發(fā)送的消息和本地事務(wù)一起提交到DB,借助DB的事務(wù)管理確保消息持久化。步驟2應(yīng)用通過(guò)本地消息表掃描,重試發(fā)送,確保消息可以發(fā)送成功。
三、Seata 架構(gòu)
3.1、系統(tǒng)組成
Seata有三個(gè)核心組件:
- Transaction Coordinator(TC,事務(wù)協(xié)調(diào)器)—— 維護(hù)全局事務(wù)和分支事務(wù)的狀態(tài),驅(qū)動(dòng)全局事務(wù)提交或回滾。
- Transaction Manager(TM,事務(wù)管理器)—— 定義全局事務(wù)的范圍,開(kāi)始事務(wù)、提交事務(wù)、回滾事務(wù)。
- Resource Manager(RM,資源管理器):—— 管理分支事務(wù)上的資源,向TC注冊(cè)分支事務(wù),匯報(bào)分支事務(wù)狀態(tài),驅(qū)動(dòng)分支事務(wù)的提交或回滾。
三個(gè)組件相互協(xié)作,TC 以 Server 形式獨(dú)立部署,TM和RM集成在應(yīng)用中啟動(dòng),其整體交互如下:
3.2、工作模式
Seata 支持四種工作模式:
3.2.1、AT(Auto Transaction)
AT模式是Seata默認(rèn)的工作模式。需要基于支持本地 ACID 事務(wù)的關(guān)系型數(shù)據(jù)庫(kù),Java 應(yīng)用,通過(guò) JDBC 訪問(wèn)數(shù)據(jù)庫(kù)。
整體機(jī)制:
該模式是XA協(xié)議的演變,XA協(xié)議是基于資源管理器實(shí)現(xiàn),而AT并不是如此。AT的2個(gè)階段分別是:
一階段:業(yè)務(wù)數(shù)據(jù)和回滾日志記錄在同一個(gè)本地事務(wù)中提交,釋放本地鎖和連接資源。二階段:提交異步化,非??焖俚赝瓿桑换貪L通過(guò)一階段的回滾日志進(jìn)行反向補(bǔ)償。
下圖中,步驟1開(kāi)啟全局事務(wù);步驟2注冊(cè)分支事務(wù),這里對(duì)應(yīng)著一階段;步驟3提交或者回滾分支事務(wù),對(duì)應(yīng)著二階段。
特點(diǎn):
優(yōu)點(diǎn):對(duì)代碼無(wú)侵入;并發(fā)度高,本地鎖在一階段就會(huì)釋放;不需要數(shù)據(jù)庫(kù)對(duì)XA協(xié)議的支持。
缺點(diǎn):只能用在支持ACID的關(guān)系型數(shù)據(jù)庫(kù);SQL解析還不能支持全部語(yǔ)法。
3.2.2、TCC
該模式工作分為三個(gè)階段:
上圖中對(duì)于多個(gè)分支事務(wù),省略了多次出現(xiàn)的 2.* 步驟。對(duì)于全局事務(wù)執(zhí)行過(guò)程中業(yè)務(wù)應(yīng)用宕機(jī)情況,業(yè)務(wù)應(yīng)用集群中對(duì)等節(jié)點(diǎn)會(huì)通過(guò)從TC獲取相關(guān)會(huì)話,從DB加載詳細(xì)信息來(lái)恢復(fù)狀態(tài)機(jī)。
特點(diǎn):
優(yōu)點(diǎn):一階段提交本地事務(wù),無(wú)鎖,高性能;事件驅(qū)動(dòng)架構(gòu),參與者可異步執(zhí)行,高吞吐;補(bǔ)償服務(wù)易于實(shí)現(xiàn)。
缺點(diǎn):不保證隔離性。
3.2.3、XA模式
XA是基于二階段提交設(shè)計(jì)的接口標(biāo)準(zhǔn)。對(duì)于支持XA的資源管理器,借助Seata框架的XA模式,會(huì)使XA方案更簡(jiǎn)單易用。使用前提:需要分支數(shù)據(jù)庫(kù)支持XA 事務(wù),應(yīng)用為 Java應(yīng)用,且使用JDBC訪問(wèn)數(shù)據(jù)庫(kù)。
整體機(jī)制:
在 Seata 定義的分布式事務(wù)框架內(nèi),利用事務(wù)資源(數(shù)據(jù)庫(kù)、消息服務(wù)等)對(duì) XA 協(xié)議的支持,以 XA 協(xié)議的機(jī)制來(lái)管理分支事務(wù)的一種 事務(wù)模式。
執(zhí)行階段:業(yè)務(wù)sql在XA分支中執(zhí)行,由分支事務(wù)的RM管理器管理,然后執(zhí)行XA prepare。完成階段:TM根據(jù)各個(gè)分支執(zhí)行結(jié)果通過(guò)TC通知各個(gè)分支執(zhí)行XA commit或者XA rollback。
特點(diǎn):
優(yōu)點(diǎn):繼承了XA協(xié)議的優(yōu)勢(shì),事務(wù)具有強(qiáng)一致性。
缺點(diǎn):同樣繼承了XA協(xié)議的劣勢(shì),由于分支事務(wù)長(zhǎng)時(shí)間開(kāi)啟,并發(fā)度低。2.5 Seata 各模式對(duì)比
分布式事務(wù)方案沒(méi)有銀彈,根據(jù)自己的業(yè)務(wù)特性選擇合適的模式。例如追求強(qiáng)一致性,可以選擇AT和XA,存在和外部系統(tǒng)對(duì)接,可以選擇Saga模式,不能依賴本地事務(wù),可以采用TCC等等。結(jié)合各模式的優(yōu)缺點(diǎn)進(jìn)行選擇。
四、AT 模式核心實(shí)現(xiàn)
鑒于Seata支持的模式較多,而其默認(rèn)的模式是AT,為節(jié)省篇幅,以下圍繞AT模式分析其相關(guān)的核心模塊實(shí)現(xiàn)。
4.1、事務(wù)協(xié)調(diào)器的啟動(dòng)
TC(事務(wù)協(xié)調(diào)器)以獨(dú)立的服務(wù)啟動(dòng),作為Server,維護(hù)全局事務(wù)和分支事務(wù)的狀態(tài),驅(qū)動(dòng)全局事務(wù)提交或回滾。下面是TC的啟動(dòng)流程:
4.2、事務(wù)管理器的啟動(dòng)
TM(事務(wù)管理器)集成在應(yīng)用中啟動(dòng),負(fù)責(zé)定義全局事務(wù)的范圍,開(kāi)始事務(wù)、提交事務(wù)、回滾事務(wù)。
TM所在應(yīng)用中需要配置GlobalTransactionScannerbean,在應(yīng)用啟動(dòng)時(shí)會(huì)進(jìn)行如下初始化流程:
4.3、資源管理器的啟動(dòng)
RM(資源管理器)集成在應(yīng)用中啟動(dòng),負(fù)責(zé)管理分支事務(wù)上的資源,向TC注冊(cè)分支事務(wù),匯報(bào)分支事務(wù)狀態(tài),驅(qū)動(dòng)分支事務(wù)的提交或回滾。
RM所在的應(yīng)用中除了需要跟TM一樣配置GlobalTransactionScanner以啟動(dòng)RMClient,還需要配置DataSourceProxy,以實(shí)現(xiàn)對(duì)數(shù)據(jù)源訪問(wèn)代理。該數(shù)據(jù)源代理實(shí)現(xiàn)了sql的解析 →生成undo-log →業(yè)務(wù)sql和undo-log一并本地提交等操作。
4.4、全局事務(wù)的工作流程
下面以一個(gè)簡(jiǎn)單的例子來(lái)說(shuō)明全局事務(wù)的工作原理:
- BusinessService:發(fā)起購(gòu)買服務(wù)
- StorageService:庫(kù)存管理服務(wù)
購(gòu)買操作實(shí)現(xiàn)在businessService.purchase中,purchase方法實(shí)現(xiàn)上通過(guò)GlobalTransaction注解,通過(guò)Dubbo服務(wù),調(diào)用了庫(kù)存服務(wù)deduct方法方法,樣例如下:
@GlobalTransactional(timeoutMills = 300000, name = "dubbo-demo-tx") public void purchase(String userId, String commodityCode, int orderCount) { storageService.deduct(commodityCode, orderCount); // throw new RuntimeException("xxx"); }
4.4.1、成功的全局事務(wù)處理流程
4.4.2、成功的全局事務(wù)處理流程
這里設(shè)定BusinessService在成功調(diào)用StorageService后,本地出現(xiàn)異常。
4.5、寫隔離實(shí)現(xiàn)
全局事務(wù)未提交,分支事務(wù)本地已經(jīng)提交的情況下(假設(shè)修改了資源A),如何避免其他事務(wù)在此時(shí)修改資源A?Seata采用全局鎖來(lái)實(shí)現(xiàn),其流程如下:
4.6、讀隔離實(shí)現(xiàn)
在數(shù)據(jù)庫(kù)本地隔離級(jí)別為讀已提交或以上的基礎(chǔ)上,Seata提供了讀未提交,這個(gè)很好理解,全局事務(wù)提交前分支事務(wù)本地已經(jīng)提交。如果想要實(shí)現(xiàn)讀已提交,則需要在select語(yǔ)句上加for update。
五、總結(jié)
Seata是Java領(lǐng)域很強(qiáng)大的分布式事務(wù)框架,其支持了多種模式。其中默認(rèn)支持的AT模式,相比于傳統(tǒng)的2PC協(xié)議(基于數(shù)據(jù)庫(kù)的XA協(xié)議),很好地解決了2PC長(zhǎng)期鎖資源的問(wèn)題,提高了并發(fā)度。Seata支持的各個(gè)模式中,AT模式對(duì)業(yè)務(wù)零入侵實(shí)現(xiàn)分布式事務(wù),對(duì)于開(kāi)發(fā)者更加友好。另外Seata的Server在選擇合適的存儲(chǔ)介質(zhì)時(shí)可以進(jìn)行集群模式,減少單點(diǎn)故障影響。
以上就是一文了解Seata的實(shí)現(xiàn)原理的詳細(xì)內(nèi)容,更多關(guān)于Seata原理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- springboot cloud使用eureka整合分布式事務(wù)組件Seata 的方法
- SEATA事務(wù)服務(wù)DOCKER部署的過(guò)程詳解
- seata-1.4.0安裝及在springcloud中使用詳解
- 詳解SpringCloud-Alibaba-Seata分布式事務(wù)
- 解決seata不能使用mysql8版本的問(wèn)題方法
- Springcloud seata分布式事務(wù)實(shí)現(xiàn)代碼解析
- SpringCloud Alibaba Seata (收藏版)
- 詳解SpringBoot基于Dubbo和Seata的分布式事務(wù)解決方案
- Springcloud seata nacos環(huán)境搭建過(guò)程圖解
- SpringBoot+Dubbo+Seata分布式事務(wù)實(shí)戰(zhàn)詳解
相關(guān)文章
詳解SpringBoot 使用Spring Initializr 快速構(gòu)建工程(官方推薦)
本篇文章主要介紹了SpringBoot 使用Spring Initializr 快速構(gòu)建工程(官方推薦),非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-10-10spring的Cache注解和redis的區(qū)別說(shuō)明
這篇文章主要介紹了spring的Cache注解和redis的區(qū)別說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12ArrayList與linkedList的用法區(qū)別及擴(kuò)容方式
這篇文章主要介紹了ArrayList與linkedList的用法區(qū)別及擴(kuò)容方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03Java 內(nèi)存模型中的happen-before關(guān)系詳解
這篇文章主要為大家介紹了Java 內(nèi)存模型中的happen-before關(guān)系示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10詳解spring項(xiàng)目中如何動(dòng)態(tài)刷新bean
這篇文章主要為大家介紹了詳解spring項(xiàng)目中如何動(dòng)態(tài)刷新bean,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08spring-boot-starter-validation?校驗(yàn)參數(shù)的實(shí)現(xiàn)
參數(shù)校驗(yàn)在很多地方都可以用到,本文主要介紹了spring-boot-starter-validation?校驗(yàn)參數(shù)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04Idea自定義方法注釋模板的教程詳解(去param括號(hào)、return全類名)
這篇文章主要介紹了Idea自定義方法注釋模板(去param括號(hào)、return全類名),本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08Java獲得一個(gè)數(shù)組的指定長(zhǎng)度排列組合算法示例
這篇文章主要介紹了Java獲得一個(gè)數(shù)組的指定長(zhǎng)度排列組合算法,結(jié)合實(shí)例形式分析了java排列組合相關(guān)數(shù)組遍歷、運(yùn)算操作技巧,需要的朋友可以參考下2019-06-06SSH框架網(wǎng)上商城項(xiàng)目第21戰(zhàn)之詳解易寶支付的流程
這篇文章主要為大家詳細(xì)介紹了SSH框架網(wǎng)上商城項(xiàng)目第21戰(zhàn)之易寶支付的流程,感興趣的小伙伴們可以參考一下2016-06-06