一、背景

在上一篇文章中,咱们应用Seata整合了SpringBoot,在这篇文章中咱们应用Seata整合SpringCloud。同时有了上一篇文章的根底,此处咱们简略实现。

二、我的项目构造

三、实现性能:

实现用户下单操作,下单分为调用 账户服务 扣除余额,调用订单服务创立订单。

四、我的项目应用到的技术

Spring Cloud 、eureka、openfeign、seata 、nacos、druid、mybatis-plus

五、整合步骤

1、引入spring-cloud-starter-alibaba-seata jar包

<dependency>    <groupId>com.alibaba.cloud</groupId>    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>    <version>2021.1</version>    <exclusions>        <exclusion>            <artifactId>seata-spring-boot-starter</artifactId>            <groupId>io.seata</groupId>        </exclusion>    </exclusions></dependency><dependency>    <groupId>io.seata</groupId>    <artifactId>seata-spring-boot-starter</artifactId>    <version>1.4.2</version></dependency>


参考文档: https://seata.io/zh-cn/docs/ops/deploy-guide-beginner.html

2、波及到的业务库操作

1、业务库须要存在 undo_log 表

CREATE TABLE IF NOT EXISTS `undo_log`(    `branch_id`     BIGINT       NOT NULL COMMENT 'branch transaction id',    `xid`           VARCHAR(128) NOT NULL COMMENT 'global transaction id',    `context`       VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization',    `rollback_info` LONGBLOB     NOT NULL COMMENT 'rollback info',    `log_status`    INT(11)      NOT NULL COMMENT '0:normal status,1:defense status',    `log_created`   DATETIME(6)  NOT NULL COMMENT 'create datetime',    `log_modified`  DATETIME(6)  NOT NULL COMMENT 'modify datetime',    UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)) ENGINE = InnoDB COMMENT ='AT transaction mode undo table';

2、业务表主键

业务表中必须蕴含单列主键,如果存在多列主键,则目前只有mysql反对。

3、页面中自动更新工夫戳

业务表中最好不要自动更新工夫戳,应用手动更新,更新数据,只更新用到的数据。
比方:
表中存在10个字段,以后业务只须要更新3个字段,此时咱们更新3个字段即可,不要更新10个字段,如果update_time字段是默认更新的,则应用手动更新。

3、开启数据源代理

1、主动配置数据源代理

seata:  enabled: true  # 是否主动开启数据源代理  enable-auto-data-source-proxy: true  # 数据源代理模式,应用AT模式  data-source-proxy-mode: AT

2、手动配置AT模式数据源代理

1、配置文件敞开主动数据源代理

seata:  # 是否主动开启数据源代理  enable-auto-data-source-proxy: false

2、配置配置数据源

AT模式下返回的数据源肯定须要是 DataSourceProxy

@Bean    public DataSource dataSourceProxy() {        // 某一个数据源        XxxDataSource xxxDataSource = new XxxDataSource();        // 设置数据源的各种配置属性        xxxDataSource.setXXX("");        // 应用 DataSourceProxy 来包装一下        return new DataSourceProxy(xxxDataSource);    }

4、传递 xid

在引入了 spring-cloud-starter-alibaba-seata 后,很多都曾经实现了主动传递 xid 。同时在分布式事务完结后,须要革除xid的值。

默认实现了 feignrestweb3种形式的 xid的传递。

5、事务分组和seata server对应上

6、注册核心和配置核心

应用程序中 seata 的配置核心和 注册核心 须要和 seata server 的保持一致。

7、业务办法加上@GlobalTransactional 注解

在须要开启分布式事务的办法上退出 @GlobalTransactional 注解,开启分布式事务。

public class BusinessServiceImpl implements BusinessService {        private final OrderService orderService;    private final AccountClient accountClient;        @Override    // 开启分布式事务    @GlobalTransactional(rollbackFor = Exception.class)    public void createAccountOrder(Integer accountId, Long amount, boolean hasException) {        System.out.println("xid:" + RootContext.getXID());        // 1、近程扣减账户余额        remoteDebit(accountId, amount);                // 2、下订单        orderService.createOrder(accountId, amount);                if (hasException) {            throw new RuntimeException("产生了异样,分布式事物须要会滚");        }    }        private void remoteDebit(Integer accountId, Long amount) {        String result = accountClient.debit(accountId, amount);        log.info("近程扣减库存后果:[{}]", result);    }}

六、演示

分布式事务产生异样,事务回滚

七、残缺代码

https://gitee.com/huan1993/spring-cloud-parent/tree/master/seata/seata-springcloud-mybatis-plus

八、参考文档

1、新人文档
2、seata常见问题