微服务集成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

java 复制代码
       <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、在用户模块配置加入配置

yaml 复制代码
seata:
  enabled: true
  application-id: ${spring.application.name}
  # 客户端和服务端在同一个事务组  default_tx_group
  tx-service-group: user_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、在订单模块配置中加入配置

yaml 复制代码
seata:
  enabled: true
  application-id: ${spring.application.name}
  # 客户端和服务端在同一个事务组  default_tx_group
  tx-service-group: user_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注解实现事务

java 复制代码
    @Override
    @GlobalTransactional(rollbackFor = Exception.class,timeoutMills = 30000,name = "user_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表:

java 复制代码
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配置已经生效。

关键信息:

java 复制代码
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

用户模块 添加用户信息:

java 复制代码
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

关键信息:

java 复制代码
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。