[spring cloud] Seata分布式事务管理

这是微服务架构中为了保证数据一致性最头疼的一块骨头。

Seata (Simple Extensible Autonomous Transaction Architecture) 是阿里巴巴开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。

在单体应用中,我们靠数据库本身的事务(ACID)就够了。但在微服务中,订单服务和库存服务连接的是不同的数据库,这就需要 Seata 来充当"大管家",保证"要成功都成功,要失败都回滚"。


1. Seata 核心架构原理 (三剑客)

Seata 的设计中定义了三个核心角色,它们协同工作来完成一个全局事务:

  1. TC (Transaction Coordinator - 事务协调者)
  • 身份"大管家"(Seata Server 服务端)。
  • 职责:维护全局和分支事务的状态,驱动全局事务提交或回滚。它是独立的中间件,需要单独部署。
  1. TM (Transaction Manager - 事务管理器)
  • 身份"发起者"(通常是发起调用的微服务,如订单服务)。
  • 职责:定义全局事务的范围。它告诉 TC:"我要开启一个全局事务"、"我要提交"或"我要回滚"。
  1. RM (Resource Manager - 资源管理器)
  • 身份"参与者"(各微服务的数据库代理)。
  • 职责:管理分支事务处理的资源。它向 TC 注册分支事务,并汇报本地事务的执行状态。

生命周期流程

  1. TMTC 申请开启一个全局事务,TC 创建并返回一个唯一的 XID(全局事务 ID)。
  2. XID 会通过微服务调用链路(Feign/Dubbo)传递给所有下游服务。
  3. RM (下游服务)在执行 SQL 时,拿到 XID,向 TC 注册分支事务,将其纳入该 XID 的管辖。
  4. TM 根据所有分支的执行结果,向 TC 发起全局提交或回滚决议。
  5. TC 调度所有 RM 进行真正的提交或回滚。

2. 什么是二阶提交 (2PC)?

Seata 的模式大多基于 两阶段提交 (Two-Phase Commit) 协议的变种。

  • 第一阶段 (Prepare)

  • 所有参与者(RM)执行本地事务,但不提交(或者像 Seata AT 那样先提交但保留反悔的证据)。

  • 告诉协调者(TC):"我这边准备好了"。

  • 第二阶段 (Commit/Rollback)

  • 如果所有人都成功,TC 通知大家:"真正的提交"。

  • 只要有一个人失败,TC 通知大家:"全部回滚"。


3. Seata 的四种事务模式

Seata 根据业务场景的不同,提供了四种模式。其中 AT 模式 是主打,TCC 是高性能补充。

3.1 AT 模式 (Automatic Transaction) ------ 默认、最常用

这是 Seata 独创的模式,零侵入,开发者像写本地事务一样写代码。

  • 原理

  • 一阶段 :业务数据和回滚日志(Undo Log)在同一个本地事务中提交。

  • Seata 会拦截你的 SQL,查询更新前的数据(Before Image)和更新后的数据(After Image),生成 JSON 存入 undo_log 表。

  • 关键点:本地锁在一阶段就释放了,性能高。

  • 二阶段(提交) :异步删除 undo_log 记录(极快)。

  • 二阶段(回滚) :通过 Undo Log 生成反向 SQL(例如 UPDATE x=1 变成 UPDATE x=0)并执行,恢复数据。

  • 适用场景:基于支持事务的关系型数据库(MySQL, Oracle, PostgreSQL),且对一致性要求不是极其苛刻(允许极短时间的脏读,但 Seata 有全局锁机制防脏写)。

3.2 TCC 模式 (Try-Confirm-Cancel) ------ 高性能

不依赖数据库事务,完全靠业务代码实现。

  • 原理:你需要为每个接口写三个方法:

  • Try:资源预留(例如:冻结 100 元,库存 -1 并 冻结库存 +1)。

  • Confirm:真正的业务提交(例如:解冻金额并扣款,解冻库存并扣除)。

  • Cancel:回滚(例如:解冻金额,恢复库存)。

  • 优点:不加数据库锁,性能最强。

  • 缺点代码侵入性极强,一个功能写三个方法,还要考虑幂等性、空回滚、悬挂等问题。

  • 适用场景:对性能要求极高,或者操作的不是数据库(比如 Redis、发邮件)。

3.3 XA 模式 ------ 强一致性

利用数据库本身(MySQL 等)支持的 XA 协议。

  • 原理

  • 一阶段:执行 SQL 但不提交,持有数据库锁。

  • 二阶段:TC 通知数据库进行 Commit 或 Rollback。

  • 优点:强一致性(Strong Consistency),标准协议。

  • 缺点:性能差。因为从一阶段到二阶段结束,一直持有数据库锁,阻塞其他请求。

3.4 Saga 模式 ------ 长事务

基于状态机引擎。

  • 原理:一连串的事务操作,如果中间失败了,就由后向前依次执行补偿操作(Compensation)。
  • 适用场景:业务流程极长(比如跨行转账、老旧系统对接),不希望长时间占用数据库连接。

4. Java 代码实战 (AT 模式)

在 Spring Cloud Alibaba 中使用 AT 模式非常简单,核心就是 undo_log@GlobalTransactional 注解

第一步:数据库准备 (必须)

在每一个微服务的数据库中,都必须创建一张 undo_log 表(这是 AT 模式存放"后悔药"的地方)。
SQL 脚本可以在 Seata 官网找到。

第二步:引入依赖
xml 复制代码
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
第三步:配置 Seata (application.yml)

你需要告诉客户端 Seata Server 在哪。

yaml 复制代码
seata:
  enabled: true
  tx-service-group: my_test_tx_group # 事务分组
  service:
    vgroup-mapping:
      my_test_tx_group: default # 映射到 Seata Server 的集群名
  registry:
    type: nacos # 使用 Nacos 寻找 Seata Server
    nacos:
      server-addr: 127.0.0.1:8848
第四步:代码使用 (@GlobalTransactional)

只需要在发起全局事务的入口方法(通常是 OrderService)上加上注解即可。

java 复制代码
@Service
public class OrderService {

    @Autowired
    private StockFeignClient stockFeignClient;
    @Autowired
    private AccountFeignClient accountFeignClient;
    @Autowired
    private OrderMapper orderMapper;

    /**
     * @GlobalTransactional: 开启全局事务
     * name: 事务名称(自定义,用于排查日志)
     * rollbackFor: 指定回滚异常
     */
    @GlobalTransactional(name = "create-order-tx", rollbackFor = Exception.class)
    public void createOrder(Order order) {
        // 1. 本地操作:创建订单
        orderMapper.insert(order);
        
        // 2. 远程调用:扣减库存 (如果这里报错,Order 会回滚)
        stockFeignClient.deduct(order.getProductId(), order.getCount());
        
        // 3. 远程调用:扣减余额 (如果这里报错,Stock 和 Order 都会回滚)
        accountFeignClient.debit(order.getUserId(), order.getMoney());
        
        // 4. 模拟异常
        if (order.getMoney() < 0) {
            throw new RuntimeException("金额非法,触发全局回滚!");
        }
    }
}

5. 总结与对比表

模式 侵入性 性能 一致性 机制 适用场景
AT 最终一致 依赖 undo_log,一阶段提交 绝大多数业务开发
TCC 极高 最终一致 手写 Try/Confirm/Cancel 性能极其敏感的核心链路
XA 强一致 数据库原生 XA 协议 银行金融等绝不能出错的场景
Saga 最终一致 状态机 + 补偿机制 跨系统长流程业务
相关推荐
惊讶的猫2 小时前
nia500总结
java·spring·mybatis
重学一遍3 小时前
深啃项目第四篇-kafka
分布式·kafka
利刃大大3 小时前
【RabbitMQ】延迟队列 && 事务 && 消息分发
分布式·消息队列·rabbitmq·队列
阿里-于怀4 小时前
阿里云为何要将数据采集开发套件开源
spring·阿里云·开源·agent·loongsuite
码界奇点4 小时前
基于Spring MVC的缺陷管理系统设计与实现
java·spring·车载系统·毕业设计·mvc·源代码管理
二哈喇子!4 小时前
springboot项目运行时报错:HikariPool-1 - Exception during pool initialization.
java·spring boot·spring
清水白石0085 小时前
重构有序字典:手写一个线程安全且更快的 OrderedDict
python·安全·spring·重构
张二狗和苗翠花5 小时前
Spring Cloud Nacos + @RefreshScope + @Value实现配置项动态刷新
spring·spring cloud
rchmin5 小时前
分布式事务一致性方案介绍
分布式