Seata分布式事务实战:Spring Boot集成AT模式与常见排障方案

微服务架构下,跨服务的数据一致性问题不可避免。Seata作为阿里巴巴开源的分布式事务解决方案,AT(Automatic Transaction)模式通过自动生成回滚SQL实现两阶段提交,对业务代码侵入性极低。本文以Spring Boot集成Seata 2.2.0为例,覆盖从环境搭建到生产排障的完整流程。

Seata AT模式工作原理:全局事务与分支事务的协作机制

AT模式分为两阶段:第一阶段,各分支事务在本地提交,Seata自动记录回滚日志到undo_log表;第二阶段,全局事务协调器(TC)根据各分支事务状态决定全局提交或回滚。提交时异步删除undo_log,回滚时根据undo_log反向生成补偿SQL执行。

核心角色定义:TC(Transaction Coordinator)是事务协调器,独立部署的Seata Server,维护全局事务和分支事务的状态机;TM(Transaction Manager)是事务管理器,定义全局事务的范围,发起全局提交或回滚;RM(Resource Manager)是资源管理器,管理分支事务上的本地资源,注册分支事务并上报状态。

Seata Server部署与存储模式选型

Seata Server支持file、db、redis三种存储模式。生产环境推荐db模式,保证事务状态持久化和多节点一致性:

CREATE DATABASE seata DEFAULT CHARACTER SET utf8mb4;
USE seata;

CREATE TABLE `global_table` (
  `xid` varchar(128) NOT NULL,
  `transaction_id` bigint(20) DEFAULT NULL,
  `status` tinyint(4) NOT NULL,
  `application_id` varchar(32) DEFAULT NULL,
  `transaction_service_group` varchar(32) DEFAULT NULL,
  `transaction_name` varchar(128) DEFAULT NULL,
  `timeout` int(11) DEFAULT NULL,
  `begin_time` bigint(20) DEFAULT NULL,
  `application_data` varchar(2000) DEFAULT NULL,
  `gmt_create` datetime DEFAULT NULL,
  `gmt_modified` datetime DEFAULT NULL,
  PRIMARY KEY (`xid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

每个业务数据库需要创建undo_log表:

CREATE TABLE `undo_log` (
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(128) NOT NULL,
  `context` varchar(128) NOT NULL,
  `rollback_info` longblob NOT NULL,
  `log_status` int(11) NOT NULL,
  `log_created` datetime(6) NOT NULL,
  `log_modified` datetime(6) NOT NULL,
  UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Spring Boot集成Seata AT模式:业务代码改造

业务代码使用@GlobalTransactional注解开启全局事务:

@Service
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private StorageFeignClient storageFeignClient;
    @Autowired
    private AccountFeignClient accountFeignClient;

    @GlobalTransactional(name = "create-order", timeoutMills = 60000, rollbackFor = Exception.class)
    public void createOrder(OrderDTO orderDTO) {
        // 1. 创建订单(本地事务 - 订单服务)
        Order order = new Order();
        order.setUserId(orderDTO.getUserId());
        order.setProductId(orderDTO.getProductId());
        order.setCount(orderDTO.getCount());
        order.setMoney(orderDTO.getMoney());
        order.setStatus(0);
        orderMapper.insert(order);

        // 2. 扣减库存(远程调用 - 库存服务)
        storageFeignClient.decrease(orderDTO.getProductId(), orderDTO.getCount());

        // 3. 扣减账户余额(远程调用 - 账户服务)
        accountFeignClient.decrease(orderDTO.getUserId(), orderDTO.getMoney());

        // 4. 修改订单状态(本地事务)
        orderMapper.updateStatus(order.getId(), 1);
    }
}

应用配置中确保数据源代理生效:

seata:
  enabled: true
  application-id: order-service
  tx-service-group: my_tx_group
  data-source-proxy-mode: AT
  client:
    rm:
      report-success-enable: true
      async-commit-buffer-limit: 10000
      lock:
        retry-interval: 10
        retry-times: 30
    tm:
      commit-retry-count: 5
      rollback-retry-count: 5
      default-global-transaction-timeout: 60000

服务治理与高可用:Seata Server集群部署

生产环境Seata Server应部署至少3个节点,通过Nacos注册中心实现集群发现。客户端通过tx-service-group映射到集群名,Seata自动从Nacos获取集群节点列表并负载均衡。当某节点宕机时,客户端自动切换到其他节点,正在进行的全局事务由TC通过db存储恢复处理。

常见排障方案:脏写检测、超时回滚与悬挂事务

问题1:BranchTransactionRollbackFailed_Retriable(脏写检测异常)

原因:分支事务在第一阶段提交后,同一行数据被其他事务修改,导致回滚时afterImage与当前数据不一致。Seata检测到脏写后会不断重试回滚。处理方法:查看branch_table中卡住的分支事务,确认冲突来源。如果是正常业务并发操作,需要通过LockRetryController调整重试参数,或在业务层引入分布式锁避免并发。

问题2:GlobalTransactionTimeout(全局事务超时)

原因:timeoutMills设置过短,远程调用链路过长导致超时。超时后TM发起回滚,但此时分支事务可能仍在执行,产生悬挂事务。处理:调大timeoutMills,合理值为最慢调用链路耗时的2倍。检查retry-dead-threshold(默认130秒),超过此阈值后Seata停止重试并标记事务为RollbackFailed_Unretryable,需要人工介入修复。

问题3:悬挂事务清理

-- 排查悬挂事务的SQL
SELECT xid, status, gmt_create, gmt_modified 
FROM global_table 
WHERE status IN (4, 5, 6, 7, 8, 9, 10, 11, 12)
  AND gmt_modified < DATE_SUB(NOW(), INTERVAL 30 MINUTE);

-- status含义:4=RollbackRetrying, 5=RollbackFailed
-- 11=RollbackFailedTimeout, 12=RollbackFailedRetryable

强制清理前需确认各分支事务的undo_log已手动处理,否则可能导致数据不一致。

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

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

相关推荐