Java分布式事務管理框架之Seata
Seata介紹
Seata:Simple Extensible Autonomous Transaction Architecture,簡易可擴展的自治式分布式事務管理框架,其前身是fescar。是一種簡單分布式事務的解決方案。Seata 是一款開源的分布式事務解決方案,致力于提供高性能和簡單易用的分布式事務服務。Seata 將為用戶提供了 AT、TCC、SAGA 和 XA 事務模式,為用戶打造一站式的分布式解決方案。
官方文檔:https://seata.io/zh-cn/docs/overview/what-is-seata.html
三大組件
事務協(xié)調(diào)器(TC):維護全局事務和分支事務的狀態(tài),驅動全局提交或回滾,相當于是協(xié)調(diào)者。
事務管理器(TM):定義全局事務的范圍:開始全局事務,提交或回滾全局事務,相當于LCN中發(fā)起方。
資源管理器(RM):管理分支事務正在處理的資源,與TC進行對話以注冊分支事務并報告分支事務的狀態(tài),并驅動分支事務的提交或回滾,相當于是LCN中的參與方
實現(xiàn)原理
- 發(fā)起方™和我們的參與方(RM)項目啟動之后和協(xié)調(diào)者TC保持長連接;
- 發(fā)起方™調(diào)用接口之前向TC獲取一個全局的事務的id 為xid,注冊到 seata 中.Aop實現(xiàn)
- 使用feign客戶端調(diào)用接口的時候,seata重寫了feign客戶端,在請求中傳遞該xid。
- 參與方(RM)從請求頭中獲取到該xid,方法執(zhí)行完后不會立馬提交而是等待協(xié)調(diào)者告訴提交狀態(tài)。
四種事務模式
第一種、AT
使用這種模式有個前提:
- 基于支持本地 ACID 事務的關系型數(shù)據(jù)庫。
- Java 應用,通過 JDBC 訪問數(shù)據(jù)庫。
實現(xiàn)過程分為兩個階段:
一階段:
在一階段中,Seata會攔截“業(yè)務SQL“,首先解析SQL語義,找到要更新的業(yè)務數(shù)據(jù),在數(shù)據(jù)被更新前,保存下來"undo",然后執(zhí)行”業(yè)務SQL“更新數(shù)據(jù),更新之后再次保存數(shù)據(jù)”redo“,最后生成行鎖,這些操作都在本地數(shù)據(jù)庫事務內(nèi)完成,這樣保證了一階段的原子性。
- 解析 SQL:得到 SQL 的類型(UPDATE),表(product),條件(where name = ‘TXC’)等相關的信息。
- 查詢前鏡像:根據(jù)解析得到的條件信息,生成查詢語句,定位數(shù)據(jù)。
- 執(zhí)行業(yè)務 SQL:更新這條記錄的 name 為 ‘GTS’。
- 查詢后鏡像:根據(jù)前鏡像的結果,通過 主鍵 定位數(shù)據(jù)。
- 插入回滾日志:把前后鏡像數(shù)據(jù)以及業(yè)務 SQL 相關的信息組成一條回滾日志記錄,插入到 UNDO_LOG 表中。
- 提交前,向 TC 注冊分支:申請 product 表中,主鍵值等于 1 的記錄的 全局鎖 。
- 本地事務提交:業(yè)務數(shù)據(jù)的更新和前面步驟中生成的 UNDO LOG 一并提交。
- 將本地事務提交的結果上報給 TC。
二階段:
相對一階段,二階段比較簡單,負責整體的回滾和提交,如果之前的一階段中有本地事務沒有通過,那么就執(zhí)行全局回滾,否在執(zhí)行全局提交,回滾用到的就是一階段記錄的"undo Log",通過回滾記錄生成反向更新SQL并執(zhí)行,以完成分支的回滾。當然事務完成后會釋放所有資源和刪除所有日志。
事務回滾的情況
- 收到 TC 的分支回滾請求,開啟一個本地事務,執(zhí)行如下操作。
- 通過 XID 和 Branch ID 查找到相應的 UNDO LOG 記錄。
- 數(shù)據(jù)校驗:拿 UNDO LOG 中的后鏡與當前數(shù)據(jù)進行比較,如果有不同,說明數(shù)據(jù)被當前全局事務之外的動作做了修改。這種情況,需要根據(jù)配置策略來做處理
- 根據(jù) UNDO LOG 中的前鏡像和業(yè)務 SQL 的相關信息生成并執(zhí)行回滾的語句
- 提交本地事務。并把本地事務的執(zhí)行結果(即分支事務回滾的結果)上報給 TC。
事務提交的情況
- 收到 TC 的分支提交請求,把請求放入一個異步任務的隊列中,馬上返回提交成功的結果給 TC。
- 異步任務階段的分支提交請求將異步和批量地刪除相應 UNDO LOG 記錄。
**總結:**AT模式是一種無侵入的分布式事務解決方案,在 AT 模式下,用戶只需關注自己的“業(yè)務 SQL”,用戶的 “業(yè)務 SQL” 作為一階段,Seata 框架會自動生成事務的二階段提交和回滾操作。該模式會根據(jù)用戶執(zhí)行的SQL生成對應的回滾數(shù)據(jù)的SQL語句,然后根據(jù)事務的提交還是回滾來執(zhí)行回滾的SQL語句還是刪除對應的UNDO LOG 記錄(SQL語句)。
第二種、TCC
不依賴于底層數(shù)據(jù)資源的事務支持:是指支持把 自定義 的分支事務納入到全局事務的管理中。
一階段 prepare 行為:調(diào)用 自定義 的 prepare 邏輯。
二階段 commit 行為:調(diào)用 自定義 的 commit 邏輯。
二階段 rollback 行為:調(diào)用 自定義 的 rollback 邏輯。
第三種、Saga
Saga模式是SEATA提供的長事務解決方案,在Saga模式中,業(yè)務流程中每個參與者都提交本地事務,當出現(xiàn)某一個參與者失敗則補償前面已經(jīng)成功的參與者,一階段正向服務和二階段補償服務都由業(yè)務開發(fā)實現(xiàn)。
第四種、XA
在 Seata 定義的分布式事務框架內(nèi),利用事務資源(數(shù)據(jù)庫、消息服務等)對 XA 協(xié)議的支持,以 XA 協(xié)議的機制來管理分支事務的一種事務模式。
使用前提:支持XA 事務的數(shù)據(jù)庫。Java 應用,通過 JDBC 訪問數(shù)據(jù)庫。
這里主要介紹使用AT模式,后續(xù)提供每種模式的實現(xiàn)方式、代碼案例。
搭建seata服務端
單機版安裝
下載地址:https://github.com/seata/seata/releases
這里使用的是1.4.2版本
學習和測試建議使用單機版,簡單搭建,生成環(huán)境不建議。
直接在github上下載對應的軟件包,一鍵啟動即可,默認是file模式,也就是數(shù)據(jù)以文件的形式保存本地。
解壓之后,進入bin目錄執(zhí)行對應的啟動命令即可:windows環(huán)境執(zhí)行 bat文件,Linux環(huán)境執(zhí)行 sh文件。


啟動成功:

數(shù)據(jù)保存在本地

集群安裝
首先準備mysql、nacos環(huán)境,在準備至少兩臺服務器,這里數(shù)據(jù)存到MySQL中去。
多個 Seata TC Server 通過 db 數(shù)據(jù)庫,實現(xiàn)全局事務會話信息的共享。同時,每個 Seata TC Server 可以注冊自己到注冊中心上,方便應用從注冊中心獲得到他們。
初始化SQL語句(可以去github中找到,源碼中也有),seata框架需要用的數(shù)據(jù)庫表

CREATE TABLE IF NOT EXISTS `global_table`
(
`xid` VARCHAR(128) NOT NULL,
`transaction_id` BIGINT,
`status` TINYINT NOT NULL,
`application_id` VARCHAR(32),
`transaction_service_group` VARCHAR(32),
`transaction_name` VARCHAR(128),
`timeout` INT,
`begin_time` BIGINT,
`application_data` VARCHAR(2000),
`gmt_create` DATETIME,
`gmt_modified` DATETIME,
PRIMARY KEY (`xid`),
KEY `idx_gmt_modified_status` (`gmt_modified`, `status`),
KEY `idx_transaction_id` (`transaction_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8;
-- the table to store BranchSession data
CREATE TABLE IF NOT EXISTS `branch_table`
(
`branch_id` BIGINT NOT NULL,
`xid` VARCHAR(128) NOT NULL,
`transaction_id` BIGINT,
`resource_group_id` VARCHAR(32),
`resource_id` VARCHAR(256),
`branch_type` VARCHAR(8),
`status` TINYINT,
`client_id` VARCHAR(64),
`application_data` VARCHAR(2000),
`gmt_create` DATETIME(6),
`gmt_modified` DATETIME(6),
PRIMARY KEY (`branch_id`),
KEY `idx_xid` (`xid`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8;
-- the table to store lock data
CREATE TABLE IF NOT EXISTS `lock_table`
(
`row_key` VARCHAR(128) NOT NULL,
`xid` VARCHAR(128),
`transaction_id` BIGINT,
`branch_id` BIGINT NOT NULL,
`resource_id` VARCHAR(256),
`table_name` VARCHAR(32),
`pk` VARCHAR(36),
`gmt_create` DATETIME,
`gmt_modified` DATETIME,
PRIMARY KEY (`row_key`),
KEY `idx_branch_id` (`branch_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8;每個seata服務節(jié)點的配置信息修改:主要修改下面兩個文件

file.conf文件的修改:注意mysql 的版本,我這里使用的是MySQL8
store {
## store mode: file、db、redis
mode = "db"
## rsa decryption public key
publicKey = ""
## database store property
db {
## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc.
datasource = "druid"
## mysql/oracle/postgresql/h2/oceanbase etc.
dbType = "mysql"
driverClassName = "com.mysql.cj.jdbc.Driver"
## if using mysql to store the data, recommend add rewriteBatchedStatements=true in jdbc connection param
url = "jdbc:mysql://www.kaicostudy.com:3306/transaction_seata?rewriteBatchedStatements=true"
user = "root"
password = "123456"
minConn = 5
maxConn = 100
globalTable = "global_table"
branchTable = "branch_table"
lockTable = "lock_table"
queryLimit = 100
maxWait = 5000
}
}registry.conf 文件的修改:
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "nacos"nacos {
application = "seata-server"
serverAddr = "www.kaicostudy.com:8848"
group = "SEATA_GROUP"
namespace = ""
cluster = "default"
username = ""
password = ""
}
}config {
# file、nacos 、apollo、zk、consul、etcd3
type = "nacos"nacos {
serverAddr = "www.kaicostudy.com:8848"
namespace = ""
group = "SEATA_GROUP"
username = ""
password = ""
dataId = "seataServer.properties"
}
}
修改好每個seata服務節(jié)點的配置信息后,正常一次啟動seata服務就可以了。之后可以在nacos看到seata服務的信息。
到此這篇關于Java分布式事務管理框架之Seata的文章就介紹到這了,更多相關Java Seata內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Servlet+MyBatis項目轉Spring Cloud微服務,多數(shù)據(jù)源配置修改建議
今天小編就為大家分享一篇關于Servlet+MyBatis項目轉Spring Cloud微服務,多數(shù)據(jù)源配置修改建議,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-01-01
Spring中@Configuration注解和@Component注解的區(qū)別詳解
這篇文章主要介紹了Spring中@Configuration注解和@Component注解的區(qū)別詳解,@Configuration 和 @Component 到底有何區(qū)別呢?我先通過如下一個案例,在不分析源碼的情況下,小伙伴們先來直觀感受一下這兩個之間的區(qū)別,需要的朋友可以參考下2023-09-09
SpringBoot中ApplicationEvent的使用步驟詳解
ApplicationEvent類似于MQ,是Spring提供的一種發(fā)布訂閱模式的事件處理方式,本文給大家介紹SpringBoot中ApplicationEvent的使用步驟詳解,感興趣的朋友跟隨小編一起看看吧2024-04-04
利用Spring Boot創(chuàng)建docker image的完整步驟
這篇文章主要給大家介紹了關于如何利用Spring Boot創(chuàng)建docker image的完整步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-08-08

