微服务集成Spring Cloud Alibaba Seata (二) 客户端连接
通过上篇文章后我们的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。