《Spring Cloud Alibaba实战》系列-集成Seata分布式事务

前言

本文演示如何使用 Seata Starter 完成 Spring Cloud 应用的分布式事务接入,Feign远程调用,AT 模式为例。

Seata是 阿里巴巴 开源的分布式事务中间件,以 高效并且对业务 0 侵入 的方式,解决 微服务 场景下面临的分布式事务问题。

准备

Seata服务端安装启动,请参考文章:《Centos7部署Seata分布式事务系统并以nacos为配置中心》

Feign的整合,请参考文章:《Spring Cloud Alibaba实战》系列-Feign之远程调用

如何开始

项目增加jar依赖

<!--Seata 分布式事务-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>

在 resource 目录下增加注册文件 registry.conf

registry {
  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  type = "nacos"

  nacos {
    serverAddr = "111.231.111.150:8848"
    namespace = ""
    cluster = "default"
  }
}
config {
  # file、nacos 、apollo、zk、consul、etcd3
  type = "nacos"

  nacos {
    serverAddr = "111.231.111.150:8848"
    namespace = ""
  }
}

配置seata代理数据源,如果不配置,事务会不起作用

public class SeataAutoConfig {

    private DataSourceProxy dataSourceProxy;

    /**
     * 主数据源
     * @return
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.dynamic.datasource.master")
    public DruidDataSource druidDataSource() {
        return new DruidDataSource();
    }

    @Bean
    @Primary
    public DataSource dataSource() {
        dataSourceProxy = new DataSourceProxy(druidDataSource());
        return dataSourceProxy;
    }

    @Bean
    public DataSourceProxy dataSourceProxy() {
        return dataSourceProxy;
    }
}

业务库中增加 undo_log

CREATE TABLE IF NOT EXISTS `undo_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(100) NOT NULL,
  `context` varchar(128) NOT NULL,
  `rollback_info` longblob NOT NULL,
  `log_status` int(11) 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=1 DEFAULT CHARSET=utf8;

yml配置(可选),不配置采取默认的也可以

# seata
seata:
  client:
    tm:
      rollback:
        retry:
          # 一阶段全局回滚结果上报TC重试次数,默认1次,建议大于1
          count: 3
      commit:
        retry:
          # 一阶段全局提交结果上报TC重试次数,默认1次,建议大于1
          count: 3

案例

新建两个springboot项目,gourd-hu(事务发起方) 和 gourd-sub,分别进行上述步骤。

接口准备

gourd-sub项目提供web接口:

gourd-hu项目准备feign调用接口,及测试方法入口:

方法入口上增加 @GlobalTransactional 注解,表示开启全局事务。

处理业务逻辑:

测试

项目集成启动成功标志,项目没有报错,并且出现下面的日志就可以了。

事务测试

事务异常情况:

发起者接口内通过feignClient 调用了sub 的两个接口,本地事务内模拟异常,测试分支事务的回滚情况。

异常抛出之前,本地事务未提交,所以log表没有记录,分支事务一阶段已结束,数据被修改,存在两条undoLog日志。

异常抛出之后,本地事务回滚,同时通知分支事务回滚数据,并异步删除undoLog。

事务正常结束情况:

发起者接口内通过feignClient 调用了sub 的两个接口,测试事务正常结束情况。

事务结束之前,本地事务未提交,所以log表没有记录,分支事务一阶段已结束,数据被修改,存在两条undoLog日志。

事务结束之后,本地事务提交,通知分支事务,异步删除undoLog。

结语

至此,springboot2.x 整合Seata 就结束啦,如果本文有错误的地方,欢迎评论指正。

===============================================

代码均已上传至本人的开源项目

葫芦胡:https://blog.csdn.net/HXNLYW/article/details/98037354

发布了92 篇原创文章 · 获赞 362 · 访问量 17万+

猜你喜欢

转载自blog.csdn.net/HXNLYW/article/details/104058926