seata xid是什麼 seata原始碼閱讀筆記

2021-10-13 07:06:34 字數 3490 閱讀 7653

seata原始碼閱讀筆記

本文基於v0.8.0版本,本文沒貼**。

seata中的三個重要部分:

tc:事務協調器,維護全域性事務和分支事務的狀態,驅動全域性提交或回滾,就是seata的服務端。

tm:事務管理器,開始全域性事務,提交或回滾全域性事務。

rm:資源管理器,管理正在處理的分支事務的資源,向tc註冊並報告分支事務的狀態,並驅動分支事務的提交或回滾。

seata的初始化

tc啟動

tm-處理全域性事務

全域性事務發起者,就是我們加@globaltransactional註解的方法,seata會**我們的方法,通過以下步驟來完成全域性事務。

傳送全域性事務開始請求到tc,tc返回xid(全域性事務唯一id),將xid繫結到當前執行緒

執行我們的業務邏輯

業務邏輯成功,傳送全域性事務commit請求到tc,如果失敗則重試

業務邏輯異常(可配置回滾規則,即哪些異常回滾),傳送全域性事務rollback請求到tc,如果失敗則重試

清理資源,事務結束

rm-處理分支事務

rm需要**我們專案中的資料來源,這一步需要我們修改自己的**,如下:

@configuration

public class datasourceconfig {

@bean

@configurationproperties(prefix = "spring.datasource")

public datasource druiddatasource() {

return new druiddatasource();

* 需要將datasourceproxy 設定為主資料來源,否則事務無法回滾

@primary

@bean("datasource")

public datasource datasource(datasource druiddatasource) {

return new io.seata.rm.datasource.datasourceproxy(druiddatasource);

**資料來源的主要目的是**資料庫連線,這樣就可以控制分支事務的commit、rollback。

seate的rm-datasoure模組中有這幾個**類datasourceproxy、connectionproxy、statementproxy,通過**jdbc中的這幾個類,讓我們的sql通過executetemplate來進行執行,這個類就是我們了解seata怎麼控制分支事務的入口。下面看分支事務的處理步驟:

將xid繫結到當前資料庫連線(xid怎麼來的?在後面)

拿到sql執行前資料庫表中的資料記錄beforeimage(只是受影響的資料及欄位,通過解析我們的sql完成)

執行我們的業務sql

拿到sql執行後資料庫表中的資料記錄afterimage

用變動資料的主鍵值作為lockkey,並儲存到當前資料庫連線中

將beforeimage和afterimage轉換成undo log,並儲存到當前資料庫連線中

向tc傳送全域性鎖請求(帶著xid和lockkey),tc返回branchid,表示拿到了全域性鎖,若不成功則重試(預設30次,每次間隔10ms);這個全域性鎖的是為了防止多個使用者同時對同一資料進行修改,造成後面通過undo_log進行回滾操作時資料出錯;這個鎖在phasetwo完成後,tc會進行釋放。

將undolog儲存到資料庫的undo_log表中

提交資料庫事務

向tc報告當前分支事務commit的結果(失敗或成功),若報告不成功則重試(預設5次)

commit成功後,清理當前資料庫連線繫結的xid

commit失敗後,向上丟擲異常,以便讓tm知道,進行全域性事務的回滾

這是phaseone的整個過程,下面看phasetwo:

tc收到tm的全域性事務提交或回滾請求後,會對這個全域性事務中的所有分支事務進行通知,rm在收到通知後,進行回滾或者提交的操作

回滾:取出資料庫undo_log進行資料補償還原,成功後刪除undo_log;提交:直接刪除undo_log

返回tc處理結果

xid在服務鏈路中的傳遞

dubbo

用dubbo的filter實現的,原始碼:io.seata.integration.dubbo.transactionpropagationfilter

原理就是:上游在filter中把xid放到rpccontext中,下游再從rpccontext拿到xid。

resttemplate和feign

對resttemplate和feign的支援不在seata-all中,而是在spring-cloud-alibaba-seata中

原始碼入口:

com.alibaba.cloud.seata.rest.seataresttemplateautoconfiguration

com.alibaba.cloud.seata.feign.seatafeignclientautoconfiguration

com.alibaba.cloud.seata.web.seatahandlerinterceptorconfiguration

原理就是:上游通過***將xid放到請求的header中,下游通過***從header中拿到xid。

seata還支援很多rpc框架,如sofa-rpc、motan等。我們也可以通過類似的方法使seata支援我們自己的rpc框架。

globallock註解

如果是用 globallock 修飾的本地業務方法,雖然該方法並非某個全域性事務下的分支事務,但是它對資料資源的操作也需要先查詢全域性鎖,如果存在其他 seata 全域性事務正在修改,則該方法也需等待。所以,如果想要seata 全域性事務執行期間,資料庫不會被其他事務修改,則該方法需要強制新增 globallock 註解,來將其納入 seata 分布式事務的管理範圍。

功能有點類似於 spring 的 @transactional 註解,如果你希望開啟事務,那麼必須新增該註解,如果你沒有新增那麼事務功能自然不生效,業務可能出 bug;seata 也一樣,如果你希望某個不在全域性事務下的 sql 操作不影響 at 分布式事務,那麼必須新增 globallock 註解。

tc的高可用設計

seata服務端支援zk、nacos、eureka等作為服務發現,通過資料庫實現資料共享,全域性事務session資訊、分支事務session資訊,全域性鎖資訊都是放在資料庫中

tcc模式

tcc和at的不同主要體現在rm這邊,tc和tm都是一樣的。

tcc的rm不會**我們的資料來源了,而是由我們自己指定rollback和commit邏輯,在二階段中,tm在發起全域性事務提交回滾時,rm只需要執行我們指定的rollback和commit方法就行了。

這種模式就是我們業務**的變動要多些,效率是要比at模式高些。

rm一階段原始碼入口:io.seata.spring.tcc.tccactioninterceptor#invoke

rm二階段原始碼入口:io.seata.rm.tcc.tccresourcemanager#branchcommit#branchrollback

參考:

你是什麼就是什麼!

不管到了什麼樣的年紀,我們都很難放棄對外表的一些執著吧。我一直要到遇見了乙個很特別很特別的人,從他身上,我才真正的懂了 外表之於乙個人的真正意義是什麼 去年,我買了新房子,本來是想委託我的小學同學幫我做室內設計,但是因為一些因素,他推薦了他口中比他更厲害的大師級設計師哥哥給我,他說大哥一直都做大飯店...

HIDL是什麼,Binder是什麼?

hidl可以用於程序間通訊 ipc 而程序間的通訊通常採用binder機制 binder是android系統程序間通訊 ipc 方式之一。linux已經擁有的程序間通訊ipc手段 internet process connection 包括 管道 pipe 訊號 signal 跟蹤 trace 插口...

shell是什麼?bash是什麼?

s 件通常指shell指令碼檔案 shell script 它是許多命令彙整寫成的乙個檔案,執行它可以一次性執行多個命令。也就是說,我們想執行乙個命令直接在命令列中輸入就可以,想執行多條命令就可以寫乙個指令碼檔案然後執行,這個道理和matlab的m檔案是一樣的。什麼是shell?shell指令碼基礎...