跳到主要内容

分布式事务

问题

分布式事务有哪些解决方案?2PC、TCC、Saga 各有什么特点?Seata 是如何实现分布式事务的?

答案

为什么需要分布式事务

微服务架构下,一个业务操作可能跨多个服务和数据库。单机事务无法保证跨节点的数据一致性。

如果订单创建成功,但库存扣减失败,就需要分布式事务来保证数据一致。

方案总览

方案一致性性能复杂度适用场景
2PC强一致传统数据库跨库
3PC强一致理论模型(少用)
TCC最终一致高性能金融场景
Saga最终一致长事务、微服务
本地消息表最终一致异步场景
MQ 事务消息最终一致异步解耦
Seata AT最终一致微服务通用

2PC(两阶段提交)

缺点

  • 同步阻塞:所有参与者在 prepare 后需等待 commit/rollback,持有资源锁
  • 单点故障:协调者宕机,参与者会一直阻塞
  • 数据不一致:协调者发出部分 commit 后宕机,部分参与者已提交、部分未提交

TCC(Try-Confirm-Cancel)

TCC 将事务拆为三个阶段,每个阶段都是本地事务:

TCC 接口示例
public interface InventoryTccService {
// Try:冻结库存(stock-10, frozen+10)
@TwoPhaseBusinessAction(name = "inventoryTry",
commitMethod = "confirm", rollbackMethod = "cancel")
boolean tryDeduct(BusinessActionContext ctx, String productId, int count);

// Confirm:真正扣减(frozen-10)
boolean confirm(BusinessActionContext ctx);

// Cancel:释放冻结(frozen-10, stock+10)
boolean cancel(BusinessActionContext ctx);
}
TCC 注意事项
  1. 空回滚:Try 未执行但收到 Cancel(网络超时场景),Cancel 需判断是否有 Try 记录
  2. 幂等:Confirm 和 Cancel 可能被重复调用,必须做幂等处理
  3. 悬挂:Cancel 先于 Try 到达,需防止 Try 在 Cancel 之后执行

Saga 模式

将长事务拆分为多个本地事务,每个本地事务有对应的 补偿操作。如果某个事务失败,逐步执行之前事务的补偿操作。

Saga 的两种实现:

模式说明优点缺点
编排(Choreography)各服务通过事件驱动,无中心协调简单、松耦合流程分散、难调试
协调(Orchestration)中心协调器控制事务流程流程清晰、易维护协调器有单点风险

本地消息表

Seata 框架

Seata 是阿里开源的分布式事务框架,支持 4 种模式:

模式说明侵入性性能
AT自动补偿(类似 2PC,基于 undo log)
TCCTry-Confirm-Cancel
Saga长事务补偿
XA数据库 XA 协议
Seata AT 模式(使用最简单)
// 只需加 @GlobalTransactional 注解
@GlobalTransactional(timeoutMills = 60000, name = "create-order")
public void createOrder(OrderDTO dto) {
// 1. 创建订单(本地事务)
orderService.create(dto);
// 2. 远程调用:扣减库存
inventoryClient.deduct(dto.getProductId(), dto.getCount());
// 3. 远程调用:扣减余额
accountClient.deduct(dto.getUserId(), dto.getAmount());
// 任意步骤失败,Seata 自动回滚所有服务
}

常见面试问题

Q1: 2PC 有什么缺点?

答案

  1. 同步阻塞:prepare 后所有参与者等待 commit,长时间持有数据库锁,性能差
  2. 单点故障:协调者宕机后参与者一直阻塞等待
  3. 数据不一致:commit 阶段协调者部分发送成功后宕机,导致部分参与者已提交、部分未提交

3PC 引入了超时机制和 preCommit 阶段,缓解了阻塞问题,但仍无法完全解决数据不一致。

Q2: TCC 和 Saga 的区别?

答案

对比TCCSaga
资源锁定Try 阶段预留资源无资源预留
一致性较强(资源冻结)较弱(无隔离)
开发成本高(每个服务写3个接口)中(正向+补偿)
适用场景高一致性要求的金融场景长事务、流程型业务
回滚方式Cancel 释放预留资源补偿操作逆向执行

Q3: 项目中怎么选择分布式事务方案?

答案

  • 强一致 + 短事务:Seata AT 或 2PC/XA
  • 强一致 + 高性能:TCC
  • 最终一致 + 异步:本地消息表 或 MQ 事务消息
  • 最终一致 + 长事务:Saga
  • 最终一致 + 简单:先写后补偿 + 定时对账

大多数互联网场景用 最终一致性 方案(MQ 事务消息 / 本地消息表)就够了,性能最好,复杂度最低。

Q4: Seata AT 模式的原理是什么?

答案

AT 模式基于 undo log 自动回滚

  1. 一阶段:拦截 SQL,在执行前记录 before image(数据快照),执行后记录 after image,生成 undo log。本地事务直接提交(释放锁)
  2. 二阶段 Commit:异步删除 undo log
  3. 二阶段 Rollback:根据 undo log 中的 before image 生成反向 SQL,执行回滚

优点是对业务零侵入(只加注解),缺点是有全局锁(TC 管理),并发性能不如 TCC。

相关链接