1. 什么是seata
Seata 是一款開源的分布式事務(wù)解決方案,致力于提供高性能和簡單易用的分布式事務(wù)服務(wù)。Seata 將為用戶提供了 AT、TCC、SAGA 和 XA 事務(wù)模式,為用戶打造一站式的分布式解決方案。
2. seata發(fā)展歷程
阿里巴巴作為國內(nèi)最早一批進行應(yīng)用分布式(微服務(wù)化)改造的企業(yè),很早就遇到微服務(wù)架構(gòu)下的分布式事務(wù)問題。阿里巴巴對于分布式事務(wù)問題先后發(fā)布了以下解決方案:
-
2014 年,阿里中間件團隊發(fā)布 TXC(Taobao Transaction Constructor),為集團內(nèi)應(yīng)用提供分布式事務(wù)服務(wù)。
-
2016 年,TXC 在經(jīng)過產(chǎn)品化改造后,以 GTS(Global Transaction Service) 的身份登陸阿里云,成為當(dāng)時業(yè)界唯一一款云上分布式事務(wù)產(chǎn)品。在阿云里的公有云、專有云解決方案中,開始服務(wù)于眾多外部客戶。
-
2019 年起,基于 TXC 和 GTS 的技術(shù)積累,阿里中間件團隊發(fā)起了開源項目 Fescar(Fast & EaSy Commit And Rollback, FESCAR),和社區(qū)一起建設(shè)這個分布式事務(wù)解決方案。
-
2019 年 fescar 被重命名為了seata(simple extensiable autonomous transaction architecture)。
-
TXC、GTS、Fescar 以及 seata 一脈相承,為解決微服務(wù)架構(gòu)下的分布式事務(wù)問題交出了一份與眾不同的答卷。
3. seata中相關(guān)事務(wù)概念
-
全局事務(wù):全局事務(wù)指的是一次性操作多個資源管理器完成的事務(wù),由一組分支事務(wù)(本地事務(wù))組成。
-
分支事務(wù)(本地事務(wù)):本地事務(wù)由本地資源管理器(通常指數(shù)據(jù)庫管理系統(tǒng) DBMS,例如 MySQL、Oracle 等)管理,嚴格地支持 ACID 特性,高效可靠。本地事務(wù)不具備分布式事務(wù)的處理能力,隔離的最小單位受限于資源管理器,即本地事務(wù)只能對自己數(shù)據(jù)庫的操作進行控制,對于其他數(shù)據(jù)庫的操作則無能為力。
4. seata的工作流程相關(guān)概念
Seata 對分布式事務(wù)的協(xié)調(diào)和控制,主要是通過 XID 和 3 個核心組件實現(xiàn)的。
XID
XID 是全局事務(wù)的唯一標(biāo)識,它可以在服務(wù)的調(diào)用鏈路中傳遞,綁定到服務(wù)的事務(wù)上下文中。
核心組件
Seata的核心組件可分為Seata服務(wù)端和Seata客戶端兩類
Seata 定義了 3 個核心組件:
-
TC(Transaction Coordinator):事務(wù)協(xié)調(diào)器,直接調(diào)度事務(wù)參與者RM。負責(zé)將RM的反饋結(jié)果響應(yīng)給TM,并聽從TM的最終決議,將具體決議(提交或回滾)發(fā)送給RM執(zhí)行。相當(dāng)于中間人,主要負責(zé)維護全局事務(wù)和分支事務(wù)的狀態(tài)。
-
TM(Transaction Manager):事務(wù)管理器,它是事務(wù)的發(fā)起者(具體的微服務(wù))。根據(jù)RM第一階段的執(zhí)行結(jié)果,進行決議。并將決議反饋給TC。相當(dāng)于發(fā)號施令的
-
RM(Resource Manager):資源管理器,其實就是事務(wù)的參與者。獲取TC的執(zhí)行命令具去執(zhí)行分支事務(wù)的第一階段以及第二階段,并將執(zhí)行結(jié)果反饋給TC,相當(dāng)于具體做事的
以上三個組件相互協(xié)作,TC 以 Seata 服務(wù)器(Server)形式獨立部署,TM 和 RM 則是以 Seata Client 的形式集成在微服務(wù)中運行。
5. seata的工作流程
TC 以 Seata 服務(wù)器(Server)形式獨立部署,TM 和 RM 則是以 Seata Client 的形式集成在微服務(wù)中運行,
整體工作流程如圖:
Seata 的整體工作流程如下:
-
TM 向 TC 申請開啟一個全局事務(wù),全局事務(wù)創(chuàng)建成功后,TC 會針對這個全局事務(wù)生成一個全局唯一的 XID(此時,由TM發(fā)起的全局事務(wù)已經(jīng)開啟)
-
XID 通過服務(wù)的調(diào)用鏈傳遞到其他服務(wù)
-
RM 向 TC 注冊一個分支事務(wù),并將其納入 XID 對應(yīng)全局事務(wù)的管轄(事務(wù)參與者執(zhí)行本地事務(wù),此時分支事務(wù)已經(jīng)執(zhí)行完成,并反饋給TC執(zhí)行結(jié)果??梢岳斫鉃锳T模式下的第一個階段)
-
TM 根據(jù) TC 收集的各個分支事務(wù)的執(zhí)行結(jié)果,向 TC 發(fā)起全局事務(wù)提交或回滾決議(事務(wù)協(xié)調(diào)者根據(jù)事務(wù)管理者的決議,發(fā)送提交或回滾的調(diào)度命令,可以理解為AT模式下的第二階段)
-
TC 調(diào)度 XID 下管轄的所有分支事務(wù)完成提交或回滾操作
6. seata的AT模式
seata中提供了了XA、TCC、SAGA、TC四種模式。其中TC模式應(yīng)用最為廣泛,可應(yīng)對大多數(shù)業(yè)務(wù)場景。也是seata的主要模式
前提
-
基于支持本地 ACID 事務(wù)的關(guān)系型數(shù)據(jù)庫。例如mysql,oracle
-
Java 應(yīng)用,通過 JDBC 訪問數(shù)據(jù)庫。(mybaits、mybatisplus、springdatajpa)
整體機制
官網(wǎng)描述:
兩階段提交協(xié)議的演變:
-
一階段:業(yè)務(wù)數(shù)據(jù)和回滾日志記錄在同一個本地事務(wù)中提交(提交前需要獲取到全局鎖),釋放本地鎖和連接資源。
-
二階段:
? ? ?提交異步化,非??焖俚赝瓿?。
? ? ?回滾通過一階段的回滾日志進行反向補償。
其實AT模式可以理解為XA二階段提交的一個變種,將二階段提交的部分在一定階段就已完成,而二階段的回滾操作是通過回滾日志完成,并是不依賴于數(shù)據(jù)庫的事務(wù)機制。也就是說一階段數(shù)據(jù)實際上已經(jīng)提交了,與此同時原子性提交的還有對應(yīng)的回滾日志
寫隔離
-
一階段本地事務(wù)提交前,需要確保先拿到 全局鎖 。
-
拿不到 全局鎖 ,不能提交本地事務(wù)。
-
拿 全局鎖 的嘗試被限制在一定范圍內(nèi),超出范圍將放棄,并回滾本地事務(wù),釋放本地鎖。此時一階段等于失敗
讀隔離
在數(shù)據(jù)庫本地事務(wù)隔離級別 讀已提交(Read Committed) 或以上的基礎(chǔ)上,Seata(AT 模式)的默認全局隔離級別是 讀未提交(Read Uncommitted) 。
如果應(yīng)用在特定場景下,必需要求全局的 讀已提交 ,目前 Seata 的方式是通過 SELECT FOR UPDATE 語句的代理。
7. seata的AT模式具體執(zhí)行流程
假設(shè)前置條件
假設(shè)當(dāng)前存在一個業(yè)務(wù)表:product
Field | Type | Key |
---|---|---|
id | bigint(20) | PRI |
name | varchar(100) | |
since | varchar(100) |
分支事務(wù)的業(yè)務(wù)邏輯:
update product set name = 'GTS' where name = 'TXC';
一階段
-
解析 SQL:得到 SQL 的類型(UPDATE),表(product),條件(where name = 'TXC')等相關(guān)的信息。
-
查詢前鏡像:根據(jù)解析得到的條件信息,生成查詢語句,定位數(shù)據(jù)。這一步的目的為了后續(xù)回滾
select id, name, since from product where name = 'TXC';
-
執(zhí)行業(yè)務(wù) SQL:更新這條記錄的 name 為 'GTS'。
-
查詢后鏡像:根據(jù)主鍵ID進行查詢。這一步的目的是為了防止存在其他線程修改數(shù)據(jù),后續(xù)比對使用
select id, name, since from product where id = 1;
-
插入回滾日志:把前后鏡像數(shù)據(jù)以及業(yè)務(wù) SQL 相關(guān)的信息組成一條回滾日志記錄,插入到 UNDO_LOG 表中
{ ? ? ?"branchId": 641789253, ? ? ? "undoItems": [{ ? ? ? ? ? ?"afterImage": { ? ? ? ? ? ? ? ? "rows": [{ ? ? ? ? ? ? ? ? ? ? ?"fields": [{ ? ? ? ? ? ? ? ? ? ? ? ? ? "name": "id", ? ? ? ? ? ? ? ? ? ? ? ? ? ?"type": 4, ? ? ? ? ? ? ? ? ? ? ? ? ? ?"value": 1 ? ? ? ? ? ? ? ? ? ? ? }, { ? ? ? ? ? ? ? ? ? ? ? ? ? ?"name": "name", ? ? ? ? ? ? ? ? ? ? ? ? ? ?"type": 12, ? ? ? ? ? ? ? ? ? ? ? ? ? ?"value": "GTS" ? ? ? ? ? ? ? ? ? ? ?}, { ? ? ? ? ? ? ? ? ? ? ? ? ? ?"name": "since", ? ? ? ? ? ? ? ? ? ? ? ? ? ?"type": 12, ? ? ? ? ? ? ? ? ? ? ? ? ? "value": "2014" ? ? ? ? ? ? ? ? ? ? }] ? ? ? ? ? ? ? ?}], ? ? ? ? ? ? ? "tableName": "product" ? ? ? ? ?}, ? ? ? ? "beforeImage": { ? ? ? ? ? ? ? ? ??"rows": [{ ? ? ? ? ? ? ? ? ? ? ? ? ? ?"fields": [{ ? ? ? ? ? ? ? ? ? ? ? ? ? ?"name": "id", ? ? ? ? ? ? ? ? ? ? ? ? ? ?"type": 4, ? ? ? ? ? ? ? ? ? ? ? ? ? ?"value": 1 ? ? ? ? ? ? ? ? ?? ?}, { ? ? ? ? ? ? ? ? ? ? ? ? ? ?"name": "name", ? ? ? ? ? ? ? ? ? ? ? ? ? ?"type": 12, ? ? ? ? ? ? ? ? ? ? ? ? ? ?"value": "TXC" ? ? ? ? ? ? ? ? ? ? }, { ? ? ? ? ? ? ? ? ? ? ? ? ? ? "name": "since", ? ? ? ? ? ? ? ? ? ? ? ? ? ? "type": 12, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"value": "2014" ? ? ? ? ? ? ? ? ? ??}] ? ? ? ? ? ? ? }], ? ? ? ? ? ? ?"tableName": "product" ? ? ?? ? }, ? ? ? ? ? "sqlType": "UPDATE" ?? ? }], ? ? ?"xid": "xid:xxx" }
-
提交前,向 TC 注冊分支:申請 product 表中,主鍵值等于 1 的記錄的 全局鎖 。
-
本地事務(wù)提交:業(yè)務(wù)數(shù)據(jù)的更新和前面步驟中生成的 UNDO LOG 一并提交。
-
將本地事務(wù)提交的結(jié)果上報給 TC。
二階段-提交
相關(guān)業(yè)務(wù)在一階段已經(jīng)提交了,二階段只需要刪除已經(jīng)沒有用處的回滾日志即可。同時還是異步刪除,效率更高
-
收到 TC 的提交指令,把請求放入一個異步任務(wù)的隊列中,馬上返回提交成功的結(jié)果給 TC。
-
異步任務(wù)階段將異步和批量地刪除相應(yīng) UNDO LOG 記錄。
二階段-回滾
相關(guān)業(yè)務(wù)在一階段已經(jīng)提交了,所以二階段的回滾相當(dāng)于又開啟了一個事務(wù)。一階段保存的后鏡像來用于對比是否有其他動作修改了這條數(shù)據(jù),一階段保存的前鏡像用于回滾語句的生成
-
收到 TC 的回滾指令,開啟一個本地事務(wù),執(zhí)行如下操作。
-
通過 XID 和 Branch ID 查找到相應(yīng)的 UNDO LOG 記錄。
-
數(shù)據(jù)校驗:拿 UNDO LOG 中的后鏡像與當(dāng)前數(shù)據(jù)進行比較,如果有不同,說明數(shù)據(jù)被當(dāng)前全局事務(wù)之外的動作做了修改。這種情況,需要根據(jù)配置策略來做處理
-
根據(jù) UNDO LOG 中的前鏡像和業(yè)務(wù) SQL 的相關(guān)信息生成并執(zhí)行回滾的語句,同時刪除已經(jīng)無用的回滾日志文章來源:http://www.zghlxwxcb.cn/news/detail-781878.html
update product set name = 'TXC' where id = 1;
-
提交本地事務(wù)。并把本地事務(wù)的執(zhí)行結(jié)果(即分支事務(wù)補償?shù)慕Y(jié)果)上報給 TC。文章來源地址http://www.zghlxwxcb.cn/news/detail-781878.html
到了這里,關(guān)于【分布式事務(wù)】Seata 開源的分布式事務(wù)解決方案的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!