文章目录
- 1. 参与者(Participant)的超时
- **超时刻点:**
- **应对的情况:**
- 2. 协调者(Coordinator)的超时
- **超时刻点:**
- **应对的情况:**
- 3. 为什么 2PC 不敢用这种超时?
- 总结表
在分布式事务中,3PC(Three-Phase Commit)相比2PC(Two-Phase Commit)的核心改进之一就是引入了双向超时机制。
不仅协调者(Coordinator)有超时机制,参与者(Participant)也引入了超时机制。以下是具体的时刻和应对的场景:
1. 参与者(Participant)的超时
这是 3PC 最关键的改变。在 2PC 中,参与者如果收不到协调者的指令,会进入无限期的阻塞等待;而在 3PC 中,参与者在特定阶段会“主动出击”。
超时刻点:
- 在
PreCommit阶段之后:参与者在发送完PreCommit的 ACK(确认为准备就绪)后,如果长时间没有收到协调者发来的doCommit(最终提交)或abort(回滚)指令,就会触发超时。
应对的情况:
- 协调者故障/单点失效:如果协调者在下发最终提交指令前宕机了,或者由于网络分区导致参与者收不到指令。
- 策略:参与者一旦超时,会默认执行 Commit(提交)操作。
- 逻辑依据:既然已经走到了
PreCommit阶段,说明在第一阶段(CanCommit)时,所有参与者都已经反馈过“我没问题”。因此,最终全局成功的概率极高,超时提交虽然仍有风险(比如协调者其实发的是回滚指令),但能有效解除阻塞。
- 逻辑依据:既然已经走到了
2. 协调者(Coordinator)的超时
协调者在 3PC 的三个阶段中依然保留了超时机制,类似于 2PC 的逻辑。
超时刻点:
- 在
CanCommit阶段:发出询问后,等待参与者的响应。 - 在
PreCommit阶段:发出预提交指令后,等待参与者的 ACK。
应对的情况:
- 参与者故障或网络延迟:如果某个参与者挂了,或者由于网络抖动没回消息。
- 策略:协调者一旦发现超时未收到全员反馈,会立即判定事务失败,向所有参与者发送
abort(中断/回滚)指令。
3. 为什么 2PC 不敢用这种超时?
你可能会问:为什么 2PC 的参与者不能超时自动提交?
- 2PC 的结构缺失:2PC 只有两个阶段。在第一阶段(Prepare)之后,参与者并不知道其他人的状态。如果此时参与者超时自动提交,而另一个参与者其实返回了“Fail”,就会导致严重的数据不一致。
- 3PC 的缓冲层:3PC 增加的
PreCommit阶段充当了“缓冲期”。进入这个阶段的前提是“第一阶段全员通过”。虽然 3PC 仍不能 100% 避免数据不一致(比如协调者在第二阶段发送了回滚,但某个参与者由于网络延迟没收到而超时提交了),但它解决了同步阻塞问题,让参与者能释放资源。
总结表
| 触发主体 | 阶段 | 超时后的动作 | 解决的问题 |
|---|---|---|---|
| 协调者 | CanCommit/PreCommit | 发送abort(中断) | 防止因某个参与者故障导致全局死等。 |
| 参与者 | PreCommit之后 | 自动执行doCommit | 防止因协调者宕机导致参与者长时间锁定资源(解除阻塞)。 |
作为一名 Java 后端开发者,理解这个对你研究Seata等分布式事务中间件的底层逻辑(比如 AT 模式与 XA 模式的区别)非常有帮助。3PC 虽然解决了阻塞,但由于多了一次网络交互,性能开销更大,且依然存在脑裂导致的数据不一致问题,所以现实中 XA(类 2PC)和 TCC 依然是主流。