【分布式事务】2PC的回滚原理
2PC的回滚原理,保证通俗易懂!
1. 场景设定
- 协调者:银行总行(负责指挥)
- 参与者:分行A(操作小张的账户)和分行B(操作小丽的账户)
- 操作:小张向小丽转账100元
2. 正常流程(两阶段提交)
sequenceDiagram
participant 总行
participant 分行A
participant 分行B
总行->>分行A: 第一阶段:准备扣款(不真扣钱)
总行->>分行B: 第一阶段:准备收款(不真加钱)
分行A-->>总行: 可以扣款(临时冻结100元)
分行B-->>总行: 可以收款(临时记账+100)
总行->>分行A: 第二阶段:正式扣款
总行->>分行B: 第二阶段:正式加钱
3. 如果某个参与者失败(比如分行B宕机)
第一阶段就失败:
- 总行问分行B:“能收款吗?”
→ 分行B没响应(或直接拒绝) - 总行立刻下令所有分行回滚:
- 对分行A说:“取消小张的冻结!”
- 结果:小张的钱原封不动,就像什么都没发生过。
第二阶段才失败:
- 分行A已扣款,但分行B加钱时宕机
- 总行发现后,启动回滚:
- 命令分行A:“把小张的100元加回去!”(用事前记录的日志恢复)
- 结果:小张的钱退回账户,小丽没收到钱。
4. 回滚的核心原理
关键设计:
-
日志记录:
- 每个参与者在准备阶段会记录原始数据快照(比如小张原本有200元)。
- 就像会计做账前先抄一遍旧数据。
-
锁资源:
- 准备阶段会冻结相关数据(小张的100元被临时锁定,其他人不能动)。
-
超时机制:
- 如果参与者长时间没响应,协调者会自动触发回滚。
代码示例(伪代码):
// 参与者(分行)的回滚逻辑
public void rollback() {
if (hasPrepared) { // 如果准备阶段成功了
// 1. 查日志找到原始数据
AccountSnapshot snapshot = log.getSnapshot();
// 2. 恢复数据
account.setBalance(snapshot.originalBalance);
// 3. 释放锁
lock.release();
}
}
5. 为什么能保证回滚成功?
- 事前留底:准备阶段记录了“后悔药”(日志)。
- 强制锁定:在回滚前,相关数据不能被其他操作修改。
- 超时兜底:就算协调者宕机,参与者等不到指令也会自动回滚。
6. 现实类比
- 就像网购付款:
- 你先提交订单(准备阶段冻结金额)。
- 如果商家发货失败,平台会自动取消订单,把钱退给你(回滚)。
- 如果一切正常,才真正扣款(提交)。
7. 一句话总结
2PC的回滚,就是协调者发现有人掉链子时,命令所有人“按事前记的账本恢复原状”,保证不会有人多扣钱或少收钱!
这样是不是清楚多了? 😊
❤️ 如果你喜欢这篇文章,请点赞支持! 👍 同时欢迎关注我的博客,获取更多精彩内容!
本文来自博客园,作者:佛祖让我来巡山,转载请注明原文链接:https://www.cnblogs.com/sun-10387834/p/18924988