目录
  • 一、背景
  • 二、项目结构
  • 三、实现功能:
  • 四、项目使用到的技术
  • 五、整合步骤
    • 1、引入spring-cloud-starter-alibaba-seata jar包
    • 2、涉及到的业务库操作
      • 1、业务库需要存在 undo_log 表
      • 2、业务表主键
      • 3、页面中自动更新时间戳
    • 3、开启数据源代理
      • 1、自动配置数据源代理
      • 2、手动配置AT模式数据源代理
    • 4、传递 xid
      • 5、事务分组和seata server对应上
        • 6、注册中心和配置中心
          • 7、业务方法加上@GlobalTransactional 注解
          • 六、演示
            • 七、完整代码
              • 八、参考文档

                一、背景

                在上一篇文章中,我们使用Seata整合了SpringBoot,在这篇文章中我们使用Seata整合SpringCloud。同时有了上一篇文章的基础,此处我们简单实现。

                二、项目结构

                springcloud整合seata的实现代码

                三、实现功能:

                完成用户下单操作,下单分为调用 账户服务 扣除余额,调用订单服务创建订单。

                springcloud整合seata的实现代码

                四、项目使用到的技术

                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>

                springcloud整合seata的实现代码

                参考文档: 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的传递。

                springcloud整合seata的实现代码

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

                springcloud整合seata的实现代码

                6、注册中心和配置中心

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

                springcloud整合seata的实现代码

                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);
                    }
                }

                六、演示

                分布式事务发生异常,事务回滚

                springcloud整合seata的实现代码

                七、完整代码

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

                八、参考文档

                1、新人文档

                2、seata常见问题

                声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。