您觉得本文档还缺少什么内容?可以自己补充~
远程调用虽然带给我们很多便利,但同时也也存在很多的问题:分布式事务。本项目采用阿里开源的seata来解决分布式事务。 详情: https://github.com/seata/seata
- pom中加入依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<exclusions>
<exclusion>
<groupId>io.seata</groupId>
<artifactId>seata-all</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-all</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
- nacos中的bc-example-server.yml和 bc-demo-server.yml 加入如下配置:
bc:
database:
isSeata: true
multiTenantType: COLUMN # 任意模式都可以
- nacos中 mysql.yml 加入如下配置:
# 分布式事务相关
seata:
enabled: ${bc.database.isSeata}
enableAutoDataSourceProxy: true
tx-service-group: bc_admin_seata_tx_group
registry:
type: nacos
nacos:
server-addr: ${bc.nacos.ip}:${bc.nacos.port}
username: ${bc.nacos.username}
password: ${bc.nacos.password}
namespace: ${bc.seata.namespace}
config:
type: nacos
nacos:
server-addr: ${bc.nacos.ip}:${bc.nacos.port}
username: ${bc.nacos.username}
password: ${bc.nacos.password}
namespace: ${bc.seata.namespace}
service:
grouplist:
default: ${bc.seata.ip:}:${bc.seata.port:}
vgroup-mapping:
bc_admin_seata_tx_group: default
disable-global-transaction: false
client:
rm:
report-success-enable: false
- 参考 bc-seata 生产者模块的 SeataTxController
@PostMapping("/save/rollback")
@GlobalTransactional
public Boolean placeOrderRollback() {
Product data = Product.builder()
.name("你的名字")
.stock(123)
.build();
log.info("data={}", data);
R<Product> save = this.seataTestApi.save(data);
log.info("a={}", save);
//在这里打断点可以看到 m_product 表的数据已经插入
//但等执行完整个方法,发现 m_product 数据被删除
Order entity = Order.builder()
.code(data.getName() + "code")
.name(data.getName())
.build();
this.orderService.save(entity);
int a = 1 / 0;
return true;
}
SeataTxController 演示的4中情况
saveCommitSuccess: 正常的提交事务
- saveRollbackFail:失败的回滚! 因为没有 @GlobalTransactional 注解
- saveRollbackSuccess: 正常回滚, 是分布式事务回滚的效果
- saveRollbackSuccess2: 正常回滚, 是demo服务的本地事务回滚的效果
原理分析
在order服务的 SeataTxController类 placeOrderRollback方法 int i = 1 / 0;
这行代码打断点可以发现:
@GolbalTransaction注解开启全局事务,加了这个注解后就有一个全局唯一的XID,这个XID代表全局事务的唯一标识,比如一个业务需要A服务和B服务都存储数据,A服务先远程调用B服务存储数据,在请求头中带上XID带过去,当B服务存储数据成功后,seata会在它的log表插入1条log_statu=0的日志,里面包含了XID和需要回滚的内容,然后到了A服务存储数据,A服务存储成功后也会在seata的log表存储一条log_statu=0的日志,在AB都存储成功后,如果后续代码发生报错,就会触发seata的全局回滚功能,取出log表中对应的XID的记录,然后进行回滚,回滚完成后会删除该日志;