您觉得本文档还缺少什么内容?可以自己补充~

远程调用虽然带给我们很多便利,但同时也也存在很多的问题:分布式事务。本项目采用阿里开源的seata来解决分布式事务。 详情: https://github.com/seata/seata

  1. 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>
  1. nacos中的bc-example-server.yml和 bc-demo-server.yml 加入如下配置:
bc:
  database:
    isSeata: true
    multiTenantType: COLUMN  # 任意模式都可以
  1. 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
  1. 参考 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;
}
  1. SeataTxController 演示的4中情况

  2. saveCommitSuccess: 正常的提交事务

  3. saveRollbackFail:失败的回滚! 因为没有 @GlobalTransactional 注解
  4. saveRollbackSuccess: 正常回滚, 是分布式事务回滚的效果
  5. 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的记录,然后进行回滚,回滚完成后会删除该日志;

results matching ""

    No results matching ""