分布式事务模式:2PC、3PC、TCC、Saga 与 Seata 实践
聊到分布式事务,很多人的第一反应就是「难」。说实话,我早年做单体应用时,事务就是个 @Transactional 注解的事。直到第一次接手微服务项目,订单、库存、积分三个服务各自独立,我才真正体会到什么叫「一个扣款成功,一个回滚失败」的噩梦。
分布式事务的核心问题,说白了就是:如何让多个独立数据库的操作,看起来像一次原子操作。今天我把几种主流模式串起来讲,最后再聊聊 Seata 这个国产框架怎么帮我们省事。
一、2PC:两阶段提交
2PC 是最经典的方案,分两个阶段走:
- 准备阶段(投票):协调者问所有参与者「能提交吗?」
- 提交阶段(执行):如果都同意,就正式提交;否则全部回滚。
我在项目中见过不少团队直接用 2PC,但踩坑的也不少。最大的问题是同步阻塞——协调者挂了,参与者就得一直等。另外,2PC 是强一致性,对性能影响很大。
二、3PC:三阶段提交
3PC 是 2PC 的改进版,多了一个 CanCommit 阶段。说白了就是先问一遍「能不能干」,再走 2PC 的流程。好处是减少了阻塞时间,但坏处是引入了更多网络开销。
我个人习惯把 3PC 看作「用网络换时间」——适合网络稳定的内网环境。但说实话,实际项目中用 3PC 的并不多,因为复杂度上去了,收益有限。
三、TCC:补偿型事务
TCC 是 Try-Confirm-Cancel 的缩写。我特别喜欢这个模式,因为它不依赖数据库锁,性能好很多。
- Try:预留资源(比如冻结库存)
- Confirm:确认执行(扣减库存)
- Cancel:回滚释放(解冻库存)
我曾经在一个电商项目中用 TCC 处理库存扣减。注意,TCC 需要业务方自己实现 Cancel 逻辑,不能偷懒。比如你 Try 阶段冻结了 10 件商品,Cancel 时就得解冻 10 件,不能多也不能少。
四、Saga:长事务模式
Saga 把一个大事务拆成多个小事务,每个小事务都有对应的补偿操作。如果某个小事务失败,就依次执行前面所有事务的补偿。
举个例子:下单 -> 扣库存 -> 扣积分。如果扣积分失败,就补偿:加回库存 -> 取消订单。
Saga 有两种实现方式:
- 编排式(Choreography):每个服务自己发事件,别人监听。适合简单链路。
- 协调式(Orchestration):一个协调器统一调度。适合复杂链路。
我个人更推荐协调式,因为编排式的事件流一旦复杂起来,调试起来真的很头疼。
五、Seata 框架实践
Seata 是阿里开源的分布式事务框架,支持 AT、TCC、Saga 和 XA 四种模式。我项目中用得最多的是 AT 模式——它自动帮你生成反向 SQL,几乎无侵入。
下面是一个简单的 Seata AT 配置示例:
// 1. 引入依赖(Spring Boot)
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.6.1</version>
</dependency>
// 2. 配置 application.yml
seata:
enabled: true
application-id: order-service
tx-service-group: my_test_tx_group
service:
vgroup-mapping:
my_test_tx_group: default
grouplist:
default: 127.0.0.1:8091
// 3. 在业务方法上加注解
@GlobalTransactional
public void createOrder(Order order) {
orderDao.insert(order); // 本地事务
stockService.deduct(order); // 远程调用
pointService.add(order); // 远程调用
}
你看,代码几乎没变,就加了一个 @GlobalTransactional。Seata 会自动拦截 SQL,生成 undo_log,在失败时回滚。
六、模式对比与选型
| 模式 | 一致性 | 性能 | 侵入性 | 典型场景 |
|---|---|---|---|---|
| 2PC | 强 | 低 | 低 | 短事务、低并发 |
| 3PC | 强 | 中 | 低 | 内网稳定环境 |
| TCC | 最终 | 高 | 高 | 高并发、资源预留 |
| Saga | 最终 | 高 | 中 | 长事务、异步链路 |
| Seata AT | 最终 | 中 | 低 | 快速落地、无侵入 |
嗯,选型其实没有银弹。我个人的经验是:能不用分布式事务就不用,实在躲不过,优先考虑 Seata AT 或 TCC。Saga 适合异步场景,2PC 尽量少碰。
七、核心知识体系图
下面这张图帮你理清几种模式的关系和选型思路:
八、总结
分布式事务没有完美的方案,只有适合的方案。我这些年做下来,最大的体会是:先想清楚业务能不能接受最终一致性。如果能,TCC 和 Saga 是首选;如果不能,再考虑 2PC 或 Seata AT。
另外,别忘了 Seata 这个好工具。它把很多底层细节封装好了,让我们能专注于业务。嗯,如果你刚开始接触分布式事务,我建议先从 Seata AT 入手,跑通一个 demo 再说。