【分布式事务】2PC和TCC区别
2PC和TCC在流程上确实有相似之处(都有“准备-提交”的阶段化操作),但它们的核心设计思想和适用场景完全不同。我用一个对比表格+生活比喻帮你彻底理清区别:
核心区别对比表
| 维度 | 2PC(两阶段提交) | TCC(Try-Confirm-Cancel) |
|---|---|---|
| 设计目标 | 保证强一致性(像银行转账) | 保证最终一致性(像网购下单) |
| 阶段名称 | Prepare + Commit/Rollback | Try + Confirm/Cancel |
| 资源锁定方式 | 数据库自动锁行(底层黑盒) | 业务代码手动预留资源(如冻结优惠券) |
| 性能影响 | 高(全程锁资源,阻塞其他操作) | 中(Try阶段后释放锁,Confirm才最终操作) |
| 业务侵入性 | 低(数据库层面实现,代码无感知) | 高(需手动写Try/Confirm/Cancel三个接口) |
| 适用场景 | 短事务、同构数据库(如MySQL XA) | 长事务、跨服务、高并发(如电商下单) |
| 失败处理 | 依赖数据库回滚 | 依赖业务补偿(如解冻资金) |
生活比喻对比
场景:网购限量商品
-
2PC模式(像银行转账):
- 准备阶段:直接冻结你的钱包余额和商品库存(完全锁定)。
- 如果支付失败:银行自动解冻余额(自动回滚)。
- 问题:其他用户在这期间完全不能买这个商品(锁库存)。
-
TCC模式(像电商实际做法):
- Try阶段:
- 扣减虚拟库存(显示“还剩10件”,但实际可超卖)。
- 冻结你的优惠券(但钱还没扣)。
- Confirm阶段:
- 真正扣款,真实库存-1(只有成功支付的用户才会走到这步)。
- Cancel阶段:
- 如果支付超时,解冻优惠券,虚拟库存加回去。
- 优势:其他用户还能看到有货(实际可能超卖,但体验更好)。
- Try阶段:
关键原理区别图示
2PC的锁机制(数据库自动控制):
flowchart TD
A[Prepare] --> B[锁定数据行]
B --> C{所有成功?}
C -->|是| D[提交并释放锁]
C -->|否| E[回滚并释放锁]
TCC的资源预留(业务手动控制):
flowchart TD
A[Try] --> B[预留资源: 冻结库存]
B --> C{所有成功?}
C -->|是| D[Confirm: 真实扣减]
C -->|否| E[Cancel: 释放预留]
代码示例对比
2PC(基于MySQL XA):
-- 完全由数据库控制,业务代码简单
XA START 'transaction_id';
UPDATE account SET balance = balance - 100 WHERE user_id = 1;
XA END 'transaction_id';
XA PREPARE 'transaction_id'; -- 准备阶段
XA COMMIT 'transaction_id'; -- 提交阶段
TCC(业务代码实现):
// 需要手动写三个接口
public class OrderService {
// Try: 预留资源
public boolean tryCreateOrder(Order order) {
// 1. 冻结库存(未真实扣减)
inventoryService.freeze(order.getItemId(), order.getCount());
// 2. 冻结优惠券
couponService.lock(order.getCouponId());
return true;
}
// Confirm: 真实提交
public boolean confirmCreateOrder(Order order) {
// 真实扣减库存
inventoryService.reduce(order.getItemId(), order.getCount());
// 真实扣优惠券
couponService.use(order.getCouponId());
return true;
}
// Cancel: 补偿释放
public boolean cancelCreateOrder(Order order) {
// 解冻库存
inventoryService.unfreeze(order.getItemId(), order.getCount());
// 返还优惠券
couponService.unlock(order.getCouponId());
return true;
}
}
如何选择?
-
用2PC当:
- 需要强一致性(如金融转账)。
- 所有参与者是同一个数据库(如MySQL跨表事务)。
-
用TCC当:
- 跨服务调用(如订单→库存→支付)。
- 高并发场景(如秒杀,允许最终一致)。
- 需要避免长事务锁竞争。
一句话总结
- 2PC是数据库层的“全自动事务”,简单但性能差。
- TCC是应用层的“手动挡事务”,灵活但要写更多代码。
就像自动挡汽车 vs 手动挡赛车,根据你的路况(业务场景)选合适的! 🚗💨
❤️ 如果你喜欢这篇文章,请点赞支持! 👍 同时欢迎关注我的博客,获取更多精彩内容!
本文来自博客园,作者:佛祖让我来巡山,转载请注明原文链接:https://www.cnblogs.com/sun-10387834/p/18924992

浙公网安备 33010602011771号