透過上篇文章後我們的Seata服務就部署成功了,如果還不清楚怎麼部署或者還沒有部署Seata服務的朋友可以看我寫的上篇文章進行服務部署。Seata部署步驟:https://www.cnblogs.com/sowler/p/18108102 接下來我們來介紹在專案中如何使用Seata,溫馨提示:請確保自己目前已經整合了一套Spring Cloud微服務架構,以更好的實操Seata。本篇只寫Seata相關的知識。
1、引入Maven依賴
首先我們需要在需要使用seata的模組引入maven依賴seata 對應版本1.3.0
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<!--自帶的版本可能會和Spring Cloud Alibaba對應的版本不一致 排除到重新引入相對應的版本 如果一致就不需要排除-->
<exclusions>
<exclusion>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
2、下載資料庫表檔案
Seata實現事務,需要依賴於資料表進行事務處理,所以我們需要下載seata對應版本的資料表匯入各各模組的資料庫裡面。下載路徑:incubator-seata/script/client/at/db/mysql.sql at v1.3.0 · apache/incubator-seata · GitHub下載成功後匯入到庫裡面。
3、在使用者模組配置加入配置
seata:
enabled: true
application-id: ${spring.application.name}
# 客戶端和服務端在同一個事務組 default_tx_group
tx-service-group: order_tx_group
# 自動資料來源代理
enable-auto-data-source-proxy: true
# 資料來源代理模式(分散式事務方案)
data-source-proxy-mode: AT
# 事務群組,配置項值為TC叢集名,需要與服務端保持一致
service:
# 跟服務端配置保持一致
vgroup-mapping:
order_tx_group: default
order-public: default
default_tx_group: default
enable-degrade: false
disable-global-transaction: false
grouplist:
default: 127.0.0.1:8091
4、在訂單模組配置中加入配置
seata:
enabled: true
application-id: ${spring.application.name}
# 客戶端和服務端在同一個事務組 default_tx_group
tx-service-group: order_tx_group
# 自動資料來源代理
enable-auto-data-source-proxy: true
# 資料來源代理模式(分散式事務方案)
data-source-proxy-mode: AT
# 事務群組,配置項值為TC叢集名,需要與服務端保持一致
service:
# 跟服務端配置保持一致
vgroup-mapping:
order_tx_group: default
order-public: default
default_tx_group: default
enable-degrade: false
disable-global-transaction: false
grouplist:
default: 127.0.0.1:8091
在需要事務的實現類業務方法上面加入@GlobalTransactional註解實現事務
@Override
@GlobalTransactional(rollbackFor = Exception.class,timeoutMills = 30000,name = "order_tx_group")
//rollbackFor 報錯異常回滾 timeoutMills 超時時間 name當前使用的那個事務組
public List<UserExternal> selectUserAll() {
//新增blog
Blog blog = new Blog();
blog.setUid(UUID.randomUUID().toString());
blog.setTitle("dubbo事務測試Test");
blog.setContent("dubbo事務測試Test啊的伺服器打");
blog.setSummary("12");
blog.setTagUid("3c16b9093e9b1bfddbdfcb599b23d835");
blogService.insert(blog);
//處理相關邏輯
Response<List<UserExternal>> response = userExternalService.selectUserAll();
// boolean flag = true;
// if (flag == true){
// throw new ParamException(500,"使用者模組出現錯誤,需要回滾");
// }
UserExternal user = new UserExternal();
user.setUserName("dubbo事務");
user.setAccount("system");
user.setEmail("dubbo@gemail.com");
Response insert = userExternalService.insert(user);
System.out.println(insert);
return response.getModel();
}
5、測試事務是否觸發
啟動專案進行資料測試。呼叫介面新增資料發現在每個模組中會有seata日誌輸出
訂單模組 新增blog表:
2024-04-03 15:09:16.383 INFO -[DefaultGlobalTransaction.java:108]- Begin new global transaction [172.25.96.1:8091:518805861666131968]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ff3054] was not registered for synchronization because synchronization is not active
JDBC Connection [io.seata.rm.datasource.ConnectionProxy@34a12e67] will not be managed by Spring
==> Preparing: INSERT INTO tb_blog (uid, title, summary, content, tag_uid) VALUES (?, ?, ?, ?, ?)
==> Parameters: 1c7cd2f7-a690-4942-b01f-9e1b76eb8b0e(String), dubbo事務測試Test(String), 12(String), dubbo事務測試Test啊的伺服器打(String), 3c16b9093e9b1bfddbdfcb599b23d835(String)
<== Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ff3054]
Response(code=200, msg=success, model=null)
2024-04-03 15:09:16.609 INFO -[DefaultGlobalTransaction.java:143]- [172.25.96.1:8091:518805861666131968] commit status: Committed
2024-04-03 15:09:16.693 INFO -[RmBranchCommitProcessor.java:56]- rm client handle branch commit process:xid=172.25.96.1:8091:518805861666131968,branchId=518805861913595905,branchType=AT,resourceId=jdbc:mysql://127.0.0.1:3306/order-mode,applicationData=null
2024-04-03 15:09:16.693 INFO -[AbstractRMHandler.java:96]- Branch committing: 172.25.96.1:8091:518805861666131968 518805861913595905 jdbc:mysql://127.0.0.1:3306/order-mode null
2024-04-03 15:09:16.693 INFO -[AbstractRMHandler.java:104]- Branch commit result: PhaseTwo_Committed
看第一行:Begin new global transaction
開始一個新的全域性事務 說明seata配置已經生效。
關鍵資訊:
2024-04-03 15:09:16.383 INFO -[DefaultGlobalTransaction.java:108]- Begin new global transaction
2024-04-03 15:09:16.609 INFO -[DefaultGlobalTransaction.java:143]- [172.25.96.1:8091:518805861666131968] commit status: Committed
2024-04-03 15:09:16.693 INFO -[RmBranchCommitProcessor.java:56]- rm client handle branch commit process:xid=172.25.96.1:8091:518805861666131968,branchId=518805861913595905,branchType=AT,resourceId=jdbc:mysql://127.0.0.1:3306/order-mode,applicationData=null
2024-04-03 15:09:16.693 INFO -[AbstractRMHandler.java:96]- Branch committing: 172.25.96.1:8091:518805861666131968 518805861913595905 jdbc:mysql://127.0.0.1:3306/order-mode null
2024-04-03 15:09:16.693 INFO -[AbstractRMHandler.java:104]- Branch commit result: PhaseTwo_Committed
使用者模組 新增使用者資訊:
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6d327c7] was not registered for synchronization because synchronization is not active
JDBC Connection [io.seata.rm.datasource.ConnectionProxy@782accbc] will not be managed by Spring
==> Preparing: INSERT INTO tb_user (user_name, account, email, create_by, create_time) VALUES (?, ?, ?, ?, ?)
==> Parameters: dubbo事務(String), system(String), dubbo@gemail.com(String), System(String), 1712128156490(Long)
<== Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6d327c7]
2024-04-03 15:09:16.707 INFO -[RmBranchCommitProcessor.java:56]- rm client handle branch commit process:xid=172.25.96.1:8091:518805861666131968,branchId=518805862223974401,branchType=AT,resourceId=jdbc:mysql://127.0.0.1:3306/user-mode,applicationData=null
2024-04-03 15:09:16.707 INFO -[AbstractRMHandler.java:96]- Branch committing: 172.25.96.1:8091:518805861666131968 518805862223974401 jdbc:mysql://127.0.0.1:3306/user-mode null
2024-04-03 15:09:16.707 INFO -[AbstractRMHandler.java:104]- Branch commit result: PhaseTwo_Committed
關鍵資訊:
2024-04-03 15:09:16.707 INFO -[RmBranchCommitProcessor.java:56]- rm client handle branch commit process:xid=172.25.96.1:8091:518805861666131968,branchId=518805862223974401,branchType=AT,resourceId=jdbc:mysql://127.0.0.1:3306/user-mode,applicationData=null
2024-04-03 15:09:16.707 INFO -[AbstractRMHandler.java:96]- Branch committing: 172.25.96.1:8091:518805861666131968 518805862223974401 jdbc:mysql://127.0.0.1:3306/user-mode null
2024-04-03 15:09:16.707 INFO -[AbstractRMHandler.java:104]- Branch commit result: PhaseTwo_Committed
檢視資料表undo_log日誌資訊,發現該資訊在事務執行時,事務資訊會新增到每個模組的undo_log日誌表中。當執行成功後,會刪除undo_log表的日誌資訊。
當事務開始執行時,檢視seata資料庫會發現在global_table表中會生成一條事務資料:
當方法執行在訂單模組處理資料的時候,會在訂單資料庫的undo_log表中新增一條資料:
當方法執行到使用者模組中時,在使用者資料庫的undo_log表中也會新增一條資料
透過上面可以發現seata是透過xid欄位的全域性ID進行事務控制的。我們還可以測試一下,當呼叫的使用者模組出現異常了,事務是如何實現回滾的。好了到此seata的在專案中的使用就介紹完畢了,我們還可以學習一些seata的執行原理來更好的使用seata。