一、背景
在上一篇文章中,咱们应用 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 的值。
默认实现了 feign
、rest
和 web
3 种形式的 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 常见问题