文章目录
- 1. 为什么说 TCC 是 2PC?
- 2. 它们之间最大的区别是什么?
- 3. 既然都是 2PC,为什么要发明 TCC?
- 痛点:解决 XA 的“长事务阻塞”
- 4. 总结
没错,你的洞察力非常敏锐。TCC 本质上就是 2PC(两阶段提交)在“业务层”的一种变阵实现。
虽然它和原生的 XA(2PC)在表现形式上大不相同,但在逻辑内核上,它们共享同一套基因。
1. 为什么说 TCC 是 2PC?
我们把 2PC 的标准定义和 TCC 放在一起对照,你一眼就能看出来:
| 阶段 | 2PC (标准模型) | TCC (业务模型) | 核心目标 |
|---|---|---|---|
| 第一阶段 | Prepare(准备) | Try(尝试) | 资源检查与预留。确认钱够不够、库存够不够,并把这部分资源锁住(冻结)。 |
| 第二阶段 | Commit(提交) | Confirm(确认) | 正式执行。真正扣掉冻结的钱,真正减掉预留的库存。 |
| 第二阶段 (异常) | Rollback(回滚) | Cancel(取消) | 释放预留。把冻结的钱还回去,把预留的库存解冻。 |
2. 它们之间最大的区别是什么?
虽然模型一样,但**“执行层”**发生了降维:
- XA (原生 2PC):是数据库在帮你玩。数据库内核负责锁行、写日志、等指令。对程序员来说是透明的(不用写代码)。
- TCC (业务 2PC):是程序员在玩。Seata 只负责传达指令,具体的
Try逻辑(比如往freeze_amount字段加钱)、Confirm逻辑、Cancel逻辑,全都得你手写 SQL实现。
3. 既然都是 2PC,为什么要发明 TCC?
你可能会想:既然 XA 已经是 2PC 了,为什么要费劲手写 TCC?
痛点:解决 XA 的“长事务阻塞”
- XA 的 2PC:第一阶段(Prepare)完成后,数据库的行锁、连接全都不能释放。如果第二阶段指令因为网络原因迟迟不到,数据库就卡死了。
- TCC 的 2PC:
- 在Try阶段,它执行的是一个完整的本地事务并提交(释放了数据库物理锁和连接)。
- 它所谓的“锁”是业务逻辑锁(比如把 100 元从
available字段转到frozen字段)。 - 核心优势:第一阶段完事后,数据库连接就还给连接池了,大大提升了高并发下的系统吞吐量。
4. 总结
TCC 是 2PC 协议在应用层的应用。
- XA叫“强一致性 2PC”(由数据库保证)。
- TCC叫“补偿型 2PC”(由业务代码保证最终一致性)。
这也是为什么在面试时,面试官问完 2PC 紧接着就会问 TCC,因为它们其实是一根藤上的两个瓜:一个是系统级的,一个是应用级的。
你现在是不是在想,既然 TCC 是手写代码,那万一Confirm或者Cancel方法执行失败了(比如网络断了),Seata 是怎么保证它一定能补救回来的?(这其实就涉及到了我们之前聊过的TC 重试机制和幂等性问题了)。