Seata分布式事务AT模式原理与Spring Boot微服务集成实战

分布式事务问题与Seata AT模式原理

微服务架构下,一个业务操作跨多个服务和多个数据库,本地事务无法保证数据一致性。Seata是阿里开源的分布式事务中间件,AT(Automatic Transaction)模式是其最常用的模式。AT模式对业务零侵入,通过自动生成补偿SQL实现回滚,适合大多数Spring Boot框架项目。

AT模式的核心机制分两阶段:一阶段拦截业务SQL,生成前置镜像(before image)和后置镜像(after image)并写入undo_log表,在本地事务中提交业务数据和undo_log;二阶段如果全局事务提交,异步删除undo_log;如果回滚,根据before image自动生成反向SQL补偿。

Seata Server部署

使用Docker部署Seata Server:

docker run -d --name seata-server \
  -p 8091:8091 \
  -p 7091:7091 \
  -e SEATA_IP=192.168.1.100 \
  -v /root/seata/config:/seata-server/resources \
  apache/seata-server:2.0.0

Seata 2.0推荐使用Nacos作为注册中心和配置中心。在application.yml中配置:

seata:
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
      namespace: ""
      dataId: seataServer.properties
  registry:
    type: nacos
    nacos:
      application: seata-server
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
      namespace: ""
  store:
    mode: db
    db:
      datasource: druid
      dbType: mysql
      url: jdbc:mysql://127.0.0.1:3306/seata
      user: root
      password: password

Spring Boot微服务接入Seata

添加依赖:

<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-spring-boot-starter</artifactId>
    <version>2.0.0</version>
</dependency>

微服务application.yml配置:

seata:
  enabled: true
  application-id: order-service
  tx-service-group: default_tx_group
  service:
    vgroup-mapping:
      default_tx_group: default
  registry:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
      dataId: seataServer.properties

每个参与分布式事务的数据库需要创建undo_log表:

CREATE TABLE `undo_log` (
  `branch_id`     BIGINT(64)  NOT NULL COMMENT 'branch transaction id',
  `xid`           VARCHAR(128) NOT NULL COMMENT 'global transaction id',
  `context`       VARCHAR(128) NOT NULL COMMENT 'undo_log context',
  `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';

高并发设计中的@GlobalTransactional使用

在业务入口方法上添加@GlobalTransactional注解开启全局事务:

@Service
public class OrderService {

    @Resource
    private OrderMapper orderMapper;
    @Resource
    private StorageFeignClient storageClient;
    @Resource
    private AccountFeignClient accountClient;

    @GlobalTransactional(name = "create-order", rollbackFor = Exception.class)
    public void createOrder(OrderDTO dto) {
        // 1. 创建订单(本地事务)
        orderMapper.insert(dto);

        // 2. 扣减库存(远程调用,独立本地事务)
        storageClient.deduct(dto.getProductId(), dto.getCount());

        // 3. 扣减余额(远程调用,独立本地事务)
        accountClient.debit(dto.getUserId(), dto.getMoney());
    }
}

如果步骤3抛出异常,Seata TC会通知步骤1和步骤2的分支事务回滚。步骤1根据undo_log中的before image生成反向SQL(DELETE订单),步骤2生成补偿SQL(恢复库存数量)。

服务治理:事务分组与隔离级别

tx-service-group定义事务分组,不同业务可以使用不同分组实现隔离。Seata AT模式的全局锁机制保证写隔离:一阶段提交前需要获取全局锁,如果另一个全局事务正在修改同一行数据,当前事务必须等待。这种机制牺牲了一定并发性能换取一致性保证。

对于读操作,AT模式提供两种隔离级别:读未提交(默认,读本地事务已提交的数据)和读已提交(通过SELECT FOR UPDATE获取全局锁后再读)。

// 读已提交隔离级别
@GlobalTransactional(rollbackFor = Exception.class)
public void transfer(Long fromId, Long toId, BigDecimal amount) {
    // 使用SELECT FOR UPDATE触发全局锁查询
    Account from = accountMapper.selectByIdForUpdate(fromId);
    Account to = accountMapper.selectByIdForUpdate(toId);

    accountMapper.deduct(fromId, amount);
    accountMapper.add(toId, amount);
}

常见问题排查

Q: 全局事务回滚但不生效,undo_log表无数据

检查数据源代理是否生效。Seata通过DataSourceProxy拦截SQL,必须确保Seata代理了业务数据源。使用seata-spring-boot-starter时自动代理,但如果手动配置了多数据源,需要用DataSourceProxy手动包装。

Q: 全局事务超时回滚

默认全局事务超时时间60秒。如果业务链路较长(多个远程调用),在@GlobalTransactional中设置timeoutMills:

@GlobalTransactional(timeoutMills = 300000, rollbackFor = Exception.class)

Q: 并发场景下出现global lock conflict

多个全局事务同时修改同一行数据。评估业务是否能接受最终一致性,如果可以考虑改用Saga模式或消息中间件实现最终一致性方案,避免全局锁争用。对于API接口规范要求高的核心交易场景,AT模式仍是平衡一致性和开发效率的合理选择。业务中台建设中,订单、库存、账户三个域的跨服务事务是典型应用场景。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/seata-fen-bu-shi-shi-wu-at-mo-shi-yuan-li-yu-springboot-wei/

(0)
小编小编
上一篇 9小时前
下一篇 9小时前

相关推荐