Seata之AT模式

2年前 (2022) 程序员胖胖胖虎阿
268 0 0

1.什么是AT模式

AT模式是Seata最主推的分布式事务解决方案,它是基于XA演进而来。AT 模式是一种无侵入的分布式事务解决方案。在 AT 模式下,用户只需关注自己的“业务 SQL”,用户的 “业务 SQL” 作为一阶段,Seata 框架会自动生成事务的二阶段提交和回滚操作。

2.AT模式的交互逻辑

AT模式的交互逻辑

3.AT模式的数据源支持

AT模式支持的数据库有:MySQL、Oracle、PostgreSQL和 TiDB

4.AT模式实践

  1. 先新建一个自己觉得合适的验证分布式事务的项目,比如两个银行转账,下单减库存等等,项目不用太复杂,就是个简单的微服务项目,依赖引入注册中心nacos,openfeign,mysql,mybatis-plus等依赖就好,能实现简单的crud就行。
  2. 然后引入seata所需依赖包,seata客户端版本的话,最好跟seata服务端版本一致,参考如下:
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
            <version>2.2.6.RELEASE</version>
            <scope>compile</scope>
        </dependency>

上述依赖点进去看的话,会发现集成了seata-spring-boot-starter,seata-all等seata所需依赖,算是很方便的依赖了。
ps:客户端建议引入1.0.0以上版本,原因是在1.0.0以上版本的seata客户端可以用yaml文件来维护seata配置项,而不用引入registry.conf和file.conf文件,从而简化了配置步骤和使项目看起来更优雅了。
3.在配置中心增加事务分组配置,可以按照项目来做分组,也可以使用默认的分组,或者还有其他情况的分组方式,分组主要是做个资源隔离,不同的分组可以对应不同的TC集群,这里以项目为切入点,建一个项目用的事务分组,但是TC集群还是用的default,增加的信息如下:
Seata之AT模式

特别注意group一定要是seata_group。
4.在项目的yml配置文件中新增seata配置,开启seata,配置如下:

seata:
  #开启seata
  enabled: true
  #事务分组,和之前定义的事务分组要一致
  tx-service-group: at-demo
  #配置中心信息
  config:
    type: nacos
    nacos:
      server-addr: localhost:8848
      #命名空间要和要应用的seata-server的命名空间一致
      namespace: dev
      group: SEATA_GROUP
      username: nacos
      password: nacos
  #注册中心信息    
  registry:
    nacos:
      server-addr: localhost:8848
      #命名空间要和要应用的seata-server的命名空间一致
      namespace: dev
      group: SEATA_GROUP
      username: nacos
      password: nacos
      application: seata-server

5.只要分布式事务链路中有涉及的业务数据库,都需要新建一个AT模式seata需要用到的undolog表,脚本如下:



SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for undo_log
-- ----------------------------
DROP TABLE IF EXISTS `undo_log`;
CREATE TABLE `undo_log` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `branch_id` bigint NOT NULL,
  `xid` varchar(100) NOT NULL,
  `context` varchar(128) NOT NULL,
  `rollback_info` longblob NOT NULL,
  `log_status` int NOT NULL,
  `log_created` datetime NOT NULL,
  `log_modified` datetime NOT NULL,
  `ext` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb3;

SET FOREIGN_KEY_CHECKS = 1;

6.在分布式事务发起者的方法上加上@GlobalTransactional(name = “at-demo”)注解,参数name表示事务名称,可以把@GlobalTransactional注解理解为单体应用的@transactional注解,只不过@GlobalTransactional注解协调管理的是分布式的事务。

5.seata事务失效情况

  1. 用于非public的方法上。
  2. 分支事务内捕获异常未抛出。
  3. 分支事务加了spring的@Transactional注解,则出现异常由spring来负责rollback,跳出了seata的管理。
  4. 异常类型不一致,seata回滚rollbackFor的类型最好是Exception。
  5. 下游服务配置了全局异常处理,导致一定会有返回值,这样下游服务出现异常,被全局异常处理后,变成了正常返回,TM就把全局事务给提交了,建议处理方案,上游服务根据返回的相应码,手动再抛出异常,这也是很正常的操作。

6.使用seata注意事项

  1. seata默认会使用方法名和参数类型来作为全局事务的名称,如果事务名称超出字段定义的长度范围,会导致开启全局事务失败,因此使用@GlobalTransactional注解建议加上name属性,自定义事务名称。
  2. 参与事务的业务表名称不要超过32varchar,防止开启全局事务失败。
  3. 在store.mode=db,由于seata是通过jdbc的executeBatch来批量插入全局锁的,根据MySQL官网的说明,连接参数中的rewriteBatchedStatements为true时,在执行executeBatch,并且操作类型为insert时,jdbc驱动会把对应的SQL优化成【insert into () values (), ()】的形式来提升批量插入的性能。 根据实际的测试,该参数设置为true后,对应的批量插入性能为原来的10倍多,因此在数据源为MySQL,同时保证5.1.13以上版本的驱动时,建议把该参数设置为true,这个选项对INSERT/UPDATE/DELETE操作都有效,具体做法:JDBC连接URL字符串中需要新增一个参数:rewriteBatchedStatements=true,参考如下:
master.jdbc.url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&rewriteBatchedStatements=true

4.如果要使用seata,一定要给每一张表都创建一个主键,最起码,目前seata是不支持没有主键的。
5.TC1.2.0版本支持mysql驱动多版本隔离,无需再添加驱动,所以为了方便最好安装1.2版本以上TC。

版权声明:程序员胖胖胖虎阿 发表于 2022年11月6日 上午8:00。
转载请注明:Seata之AT模式 | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...