Skip to content

分布式事务

2PC/3PC、TCC、Saga、本地消息表、Seata 选型。

Updated View as Markdown
For humans

分布式事务

微服务和分库分表之后,一个业务操作要跨多个数据库或服务,本地事务失效,需要分布式事务方案。主线:强一致方案(2PC/TCC)和最终一致方案(Saga/本地消息表),选型看一致性要求和吞吐。

强一致:2PC 与 3PC

2PC(两阶段提交):协调者先问所有参与者“能提交吗”(准备阶段),全部同意才广播提交,任一拒绝则全部回滚。

问题:准备阶段后协调者宕机,参与者阻塞等待;协调者单点故障;同步阻塞性能差。

3PC:在 2PC 基础上加超时机制和 CanCommit 阶段,减少阻塞窗口,但引入新问题(网络分区时可能违反一致性),实际应用少。

2PC 在分布式事务里更多作为理论基础:XA 协议就是 2PC 的数据库实现,性能开销大,高并发场景基本不用。

TCC:业务补偿

TCC(Try-Confirm-Cancel)把每个操作拆成三个方法:

  • Try:预留资源(冻结库存、冻结金额)
  • Confirm:确认执行(扣减冻结的库存)
  • Cancel:取消回滚(释放冻结)

优势:不依赖数据库锁,性能比 2PC 好。代价:业务侵入大,每个操作要写三个方法;要处理幂等、空回滚(Try 没执行就收到 Cancel)、悬挂(Cancel 先于 Try)。Seata 的 TCC 模式是生产常用选择。

Saga:最终一致

Saga 把长事务拆成一系列本地事务,每个事务有对应的补偿事务。正向执行,失败则反向补偿。两种编排:编排式(一个协调者串流程)和协同式(事件驱动,各服务自己订阅和响应)。

优势:无锁、适合长流程。代价:没有隔离性(中间状态对外可见),补偿逻辑要自己写,业务要能容忍中间状态。

本地消息表(可靠消息最终一致)

写业务和写消息表在同一个本地事务里,消息表作为“发出去的保证”:

  1. 业务操作和消息写入同事务提交
  2. 定时任务扫描未发送消息,投递 MQ
  3. 消费方处理成功后回执,标记消息已处理

变体是 Outbox 模式(用 binlog 监听替代定时扫描)。这是最终一致方案里实现最简单、最可靠的,适合异步场景。

选型

方案 一致性 性能 业务侵入 适用
XA(2PC) 低并发、强一致
TCC 核心资金类,Seata 支持
Saga 最终 长流程、跨服务
本地消息表 最终 异步、可延迟

一个务实的结论:大多数业务能接受最终一致,优先本地消息表或 Saga;只有资金类强一致场景才上 TCC。Seata 是目前最主流的分布式事务框架,支持 AT(自动补偿)、TCC、Saga 多种模式。

面试追问

  1. 2PC 的问题? 同步阻塞、协调者单点、准备后宕机参与者悬挂。是理论基础,XA 实现性能差
  2. TCC 和 2PC 的区别? TCC 用业务补偿替代数据库锁,Try 预留、Confirm 确认、Cancel 回滚。性能好但侵入大,要处理幂等、空回滚、悬挂
  3. Saga 怎么保证一致性? 正向本地事务加反向补偿事务,失败反向执行。没有隔离性,中间状态可见
  4. 本地消息表原理? 业务和消息写同事务,定时任务投递,消费回执。Outbox 用 binlog 监听替代扫描
  5. Seata 怎么选模式? AT 模式自动补偿侵入最小,TCC 适合强一致核心链路,Saga 适合长流程。能接受最终一致就别上强一致
Navigation

Type to search…

↑↓ navigate↵ selectEsc close