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ù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot敏感數(shù)據(jù)脫敏的處理方式
在Spring Boot中處理敏感數(shù)據(jù)脫敏,可以通過以下幾種方式實現(xiàn),確保敏感信息在接口返回、日志輸出、數(shù)據(jù)庫存儲等環(huán)節(jié)得到保護,文中通過代碼示例講解的非常詳細,需要的朋友可以參考下2025-03-03Apache DolphinScheduler實現(xiàn)自動化打包單機/集群部署詳解
這篇文章主要為大家介紹了Apache DolphinScheduler實現(xiàn)自動化打包單機/集群部署詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-09-09SpringBoot鉤子函數(shù)的實現(xiàn)示例
SpringBoot雖然沒有直接稱為“鉤子函數(shù)”的概念,但可以其他方法實現(xiàn),本文就來介紹一下SpringBoot鉤子函數(shù)的實現(xiàn)示例,感興趣的可以了解一下2024-11-11java基本教程之常用的實現(xiàn)多線程的兩種方式 java多線程教程
下面開始學習“常用的實現(xiàn)多線程的2種方式”:Thread 和 Runnable。之所以說是常用的,是因為通過還可以通過java.util.concurrent包中的線程池來實現(xiàn)多線程2014-01-01springmvc 傳遞和接收數(shù)組參數(shù)的實例
下面小編就為大家分享一篇springmvc 傳遞和接收數(shù)組參數(shù)的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-03-03java實現(xiàn)批量下載 多文件打包成zip格式下載
這篇文章主要為大家詳細介紹了java實現(xiàn)批量下載、將多文件打包成zip格式下載,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-07-07在SpringBoot中整合數(shù)據(jù)源的示例詳解
這篇文章主要介紹了在SpringBoot中如何整合數(shù)據(jù)源,本文介紹了如何在SpringBoot項目中整合常見的數(shù)據(jù)源,包括JdbcTemplate、MyBatis和JPA,并探討了如何配置和使用多數(shù)據(jù)源,需要的朋友可以參考下2023-06-06