一句话总结
Seata 是阿里巴巴开源的分布式事务解决方案,核心思想:全局事务 = 一组分支事务的集合,要么全部成功,要么全部回滚。三大组件:TC(Transaction Coordinator,事务协调者,独立部署)、TM(Transaction Manager,事务管理器,标注 @GlobalTransactional)、RM(Resource Manager,资源管理器,管理分支事务)。四种模式:AT(自动补偿,默认推荐)、TCC(两阶段补偿,性能好)、Saga(长事务,正向+补偿)、XA(强一致,性能差)。
初级理解
分布式事务问题
# 场景:下单流程
# 订单服务:创建订单
# 库存服务:扣减库存
# 账户服务:扣减余额
# 问题
# 订单创建成功 → 库存扣减成功 → 账户扣减失败
# 订单和库存需要回滚,但它们是不同服务、不同数据库
# 本地事务(@Transactional)无法跨服务回滚
# 解决方案:Seata 分布式事务
@GlobalTransactional // 全局事务注解
public void createOrder(OrderDTO dto) {
orderService.create(dto); // 订单服务
stockService.deduct(dto); // 库存服务
accountService.deduct(dto); // 账户服务
// 任何一步失败,前面成功的步骤自动回滚
}
中级深入
AT 模式原理
# AT 模式(Automatic Transaction)两阶段
# 一阶段:执行 SQL,记录 undo_log
# 1. 解析 SQL,获取 before-image(修改前数据)
# 2. 执行业务 SQL
# 3. 获取 after-image(修改后数据)
# 4. 将 before-image 和 after-image 写入 undo_log 表
# 5. 提交本地事务(一阶段就提交!)
# 二阶段-提交:全局事务成功
# 1. 异步删除 undo_log(清理)
# 二阶段-回滚:全局事务失败
# 1. 读取 undo_log 中的 before-image
# 2. 用 before-image 还原数据(反向 SQL)
# 3. 删除 undo_log
# 关键:一阶段就提交本地事务
# 优点:锁持有时间短,性能好
# 缺点:一阶段提交后数据对其他事务可见(脏读风险)
Seata 四大模式对比
| 模式 | 一致性 | 性能 | 侵入性 | 适用场景 |
|---|---|---|---|---|
| AT | 最终一致 | 高 | 低 | 通用场景(默认推荐) |
| TCC | 最终一致 | 很高 | 高(需写 try/confirm/cancel) | 高性能场景 |
| Saga | 最终一致 | 高 | 中 | 长事务、老系统 |
| XA | 强一致 | 低 | 低 | 强一致性要求 |
高级拓展
TCC 模式
# TCC(Try-Confirm-Cancel)模式
# Try:预留资源(检查+锁定)
# Confirm:确认提交(使用预留资源)
# Cancel:取消回滚(释放预留资源)
# 示例:账户扣款
public interface AccountTccAction {
// Try:冻结余额
@TwoPhaseBusinessAction(name = "deduct", commitMethod = "confirm", rollbackMethod = "cancel")
boolean tryDeduct(BusinessActionContext ctx, @BusinessActionContextParameter("userId") Long userId, BigDecimal amount);
// Confirm:扣减冻结余额
boolean confirm(BusinessActionContext ctx);
// Cancel:解冻余额
boolean cancel(BusinessActionContext ctx);
}
# TCC 优点
# 1. 一阶段就释放锁(Try 只预留)
# 2. 性能比 AT 更好
# 3. 不依赖数据库 undo_log
# TCC 缺点
# 1. 代码侵入性强(每个接口写三个方法)
# 2. 需要处理空回滚、悬挂、幂等
全局锁与写隔离
# AT 模式写隔离
# 问题:一阶段提交后,其他事务可能修改同一行数据
# 解决:全局锁
# 全局锁流程
# 1. 一阶段:获取本地锁 + 全局锁
# 2. 提交本地事务,释放本地锁,保留全局锁
# 3. 二阶段:释放全局锁
# 写隔离
# 事务 A 修改记录 X(持有全局锁)
# 事务 B 也要修改记录 X
# → B 需要等待 A 的全局锁释放
# → 如果 A 回滚,B 可以继续
# → 如果 A 提交,B 获取锁后执行
实战场景
场景:Seata AT 模式配置
# 1. 部署 Seata Server(TC)
# 下载 seata-server,配置注册中心和存储模式
# 2. 每个服务引入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
# 3. 每个服务配置
seata:
tx-service-group: my_tx_group # 事务分组
service:
vgroup-mapping:
my_tx_group: default # 映射到 Seata 集群
# 4. 每个数据库添加 undo_log 表
# CREATE TABLE undo_log (...)
# 5. 业务方法添加 @GlobalTransactional
@GlobalTransactional
public void createOrder(OrderDTO dto) { }
面试模拟
面试官:Seata AT 模式的原理?
你:两阶段:一阶段执行 SQL 并记录 undo_log(before-image 和 after-image),然后提交本地事务;二阶段如果全局成功则删除 undo_log,如果失败则用 before-image 反向补偿。一阶段就提交,锁持有时间短,性能好。
面试官:AT 和 TCC 有什么区别?
你:AT 自动生成回滚 SQL,对业务无侵入,但依赖数据库 undo_log。TCC 需要手写 try/confirm/cancel 三个方法,侵入性强但性能更好,不依赖数据库。AT 适合通用场景,TCC 适合高性能场景。