当前位置: 首页 > news >正文

分布式3PC理论

目录

为什么需要 3PC?

核心结论

3PC的优缺点

3PC与 Paxos / Raft 对比


本篇文章内容的前置知识为 分布式2PC理论,如果不了解,可点击链接学习

分布式2PC理论-CSDN博客

为什么需要 3PC?

1) 2PC 的根本问题:阻塞 + 不确定
2PC 两阶段:投票(prepare)→提交(commit)
一旦协调者在关键窗口宕机或网络分区,参与者会进入不确定状态——既不能提交也不敢回滚,只能无限等待协调者的最终决定。这带来两类问题:
阻塞:协调者挂了或网络中断,参与者无法自决,业务线程/锁资源被长期占用
进退两难:参与者贸然提交会破坏原子性;贸然回滚也可能与其他节点的提交相冲突
工程副作用:长时间占锁、长事务、资源饥饿、吞吐下降,甚至雪崩。

直观例子:协调者收齐所有YES后挂了。2PC 里参与者都已准备就绪,但没有最终指令,谁也不敢动,导致系统卡死。

2) 3PC 的设计目标:在可判定超时的条件下非阻塞

3PC(Three-Phase Commit)的目标不是更强一致,而是降低阻塞:
在一个同步或部分同步网络(消息延迟有明确上限 Δ)下,引入超时与一个缓冲阶段,让参与者在协调者失联时能自行做决定,不再无限等待。

3PC的关键前提假设(很重要):
故障模型为停机型(Fail-Stop):节点故障后只会停止服务,不会发送错误消息(即不作恶)
消息延迟有上限:网络传输、节点处理的延迟不会超过 Δ,因此超时可作为协调者失联的有效判定依据
无严重网络分区:若出现分区(部分节点断连),3PC 的一致性可能被破坏(见第 5 节)

同步网络:消息从发起到接收的延迟,一定≤某个明确的固定值 Δ,且节点处理消息的速度也有上限,全程可预判。
部分同步网络:大部分时候消息延迟≤Δ,但允许偶尔超出(可恢复),核心是多数情况下能按同步网络的规则决策。

3) 3PC 的核心改动:把 2PC 的准备再切半

        3PC 的核心改动是将 2PC 的 Prepare 阶段拆分为 CanCommit(预询问)和 PreCommit(预提交)两个阶段,再保留 DoCommit(正式提交)阶段,通过三阶段日志 + 超时自决规则,将 2PC 的单一不确定窗口拆分为两个可安全决策的窗口。

阶段协调者行为参与者行为超时规则(核心)
1. CanCommit(预询问)向所有参与者发送是否可提交请求,等待反馈仅自检(不占锁、不持久化关键日志),若可行返回 YES,否则返回NO

协调者:超时未收齐YES → 宣告Abort

参与者超时未收到协调者后续指令 → 直接Abort(安全,因未占资源)

2. PreCommit(预提交)仅当收齐所有YES时,发送预提交请求;否则发送Abort收到预提交后,持久化预提交完成日志(占锁、预留资源),返回ACK;收到Abort则直接回滚

协调者:超时未收齐ACK → 发送Abort

参与者超时未收到DoCommit指令 → 自主Commit(安全,因所有节点已通过预询问)

3. DoCommit(正式提交)收齐预提交ACK后,发送正式提交请求;若中途发现异常(如参与者回滚),则发送Abort收到Commit则执行提交、释放资源、删除锁;收到Abort则回滚。返回ACK给协调者

非阻塞的本质在于两条超时自决规则
3PC 通过阶段拆分,让参与者在任何超时场景下都有安全决策:
CanCommit 阶段超时:在 CanCommit 等不到协调者/指令,直接 ABORT
PreCommit 阶段超时:在 PreCommit 等不到DoCommit ,自主 COMMIT

这把 2PC 的唯一不确定窗口拆成两个:
PreCommit 之前超时 → 放弃(保证不会有人已提交)
PreCommit 之后超时 → 提交(保证大家都具备提交条件)

阶段1:CanCommit(预询问)
协调者 → 参与者:能提交吗?
参与者自检资源/逻辑,可行则回 YES,否则 NO
——超时策略:收不齐 YES => 协调者宣告 ABORT;参与者也可安全放弃阶段2:PreCommit(预提交)
条件:收齐所有 YES
协调者 → 参与者:进入“可提交态”,先落本地日志/锁资源,但还不写入最终提交;参与者回 ACK
——关键:一旦进入 PreCommit,大家都“随时可完成提交”阶段3:DoCommit(正式提交)
协调者 → 参与者:执行提交;参与者提交并释放资源,回 ACK

4) 3PC 如何缓解 2PC 的典型故障场景
用三个场景对比:
场景 A:协调者在收齐 YES 之前宕机
2PC:有人已投 YES,有人还在等,不知道最终态,可能阻塞
3PC:仍处 CanCommit,参与者超时后安全 ABORT(没人进入 PreCommit)

场景 B:协调者在发出 PreCommit 之后、DoCommit 之前宕机
2PC:所有参与者都 prepare 完成,只能无限等最终决定
3PC:大家处于 PreCommit,等不到 DoCommit 就自主 COMMIT(非阻塞)

场景 C:协调者在发出 DoCommit 之后宕机
两者都能依赖持久化日志恢复到一致提交(已收到的提交照常提交,未收到的要么等恢复、要么依据恢复协议补齐)

协调者 DoCommit 后宕机,影响是没法收参与者的最终 ACK、没法统一处理异常,但不影响一致性,因为它已发完 Commit 指令:收到的参与者正常提交,没收到的参与者靠 PreCommit 日志(知道自己该提交),重启 / 超时后也会提交,最终结果一致

重启是因为参与者有可能在 PreCommit 阶段突然宕机,宕机后内存里的状态会丢,重启时只能靠日志找回之前已进入 PreCommit 的状态,才能按规则补提交;若没宕机,超时后直接自主 Commit 即可,不用重启。

5) 3PC 仍然不万能:网络分区下可能不一致
致命边界条件:分区导致有些参与者收到 PreCommit,另一些没收到
收到 PreCommit 的那一侧:按 3PC 规则,超时会 COMMIT
未收到的一侧:按规则会 ABORT
破坏原子性
这就是为什么 3PC 的非阻塞要靠同步/无分区假设;而在真实互联网环境(异步且可能分区),3PC 不能保证强一致

6) 形式化地看:状态机与超时转移

从工程实现角度,3PC 的非阻塞和一致性依赖状态机 + 持久化日志(WAL,Write-Ahead Log) ,确保节点重启后能恢复到正确状态。

参与者的核心状态流转:
Init(初始) → Waiting(CanCommit后,待预提交) → PreCommit(预提交完成) → Commit/Abort(最终态)

状态跃迁规则:
Waiting 状态:超时 / 收到 Abort → 跳转到 Abort;收到 PreCommit → 跳转到 PreCommit
PreCommit 状态:超时 / 收到 Commit → 跳转到 Commit;收到 Abort → 跳转到 Abort
任何状态跃迁前,必须先持久化日志,防止重启后状态丢失

日志的核心作用:幂等恢复
节点宕机重启后,通过读取 WAL 日志确定自身状态:
若日志记录已进入 PreCommit → 直接执行 Commit
若日志记录仅 Waiting → 执行 Abort
若日志记录已 Commit → 无需操作(确保幂等,避免重复提交)

幂等是多次执行同一操作,结果不变;恢复是崩溃后回到崩溃前的正确状态

核心结论

        2PC 的痛点是阻塞:卡在 Prepare 后、Commit 前的不确定窗口,只能死等协调者,活性差但异步环境下安全性稳
        3PC 的改进是拆窗自救:用 CanCommit+PreCommit 拆分窗口,让参与者能按状态超时自决(Waiting→Abort/PreCommit→Commit),缓解阻塞,但代价是多一轮通信、且分区下可能分叉,需依赖同步 / 部分同步网络
        工业界少用 3PC,是因为它解决了 2PC 的阻塞,却引入了分区下的一致性风险,而 Raft/Paxos 等共识协议能在异步 + 分区环境下同时保证安全与活性,更适配复杂场景。

3PC的优缺点

优点:
比 2PC 更少阻塞。
引入超时机制,避免无限等待。

缺点:
实现复杂,消息开销大(多一轮通信)
仍不能完全解决一致性问题(极端网络分区时仍可能矛盾)
在实际工业界应用很少(数据库几乎不用 3PC)

3PC与 Paxos / Raft 对比

3PC:事务原子提交协议,目标是“分布式事务一致性”。
Paxos / Raft:分布式一致性协议,目标是“副本之间达成共识”。

区别:
3PC 偏向数据库事务。
Paxos / Raft 偏向分布式存储、日志复制。
工业界更常用 Raft / Paxos,而不是 3PC。

为啥工业界更爱 Raft/Paxos,不用 3PC?
因为 3PC 的本事太单一,只解决事务原子提交

实际场景中,事务的需求可以用更灵活的方案(如 TCC、Saga)替代,不用死磕 3PC;
副本共识(同步数据、选主)是所有分布式系统的基础刚需(比如分布式数据库、缓存集群、云服务都要),Raft/Paxos 刚好能稳定解决这个刚需,还能容忍网络分区、节点故障,比 3PC 更通用抗造。


文章转载自:

http://YGHikd3w.mwjdj.cn
http://txpMiWuB.mwjdj.cn
http://tvOGRETk.mwjdj.cn
http://YCs4CUoC.mwjdj.cn
http://tAFLdgao.mwjdj.cn
http://hMoITmKY.mwjdj.cn
http://FtwTuiP1.mwjdj.cn
http://Z8wUMbuG.mwjdj.cn
http://C1vzdWG9.mwjdj.cn
http://smvPMrCn.mwjdj.cn
http://o44WBooD.mwjdj.cn
http://hujJeKTU.mwjdj.cn
http://rKlRTxSD.mwjdj.cn
http://u0gtX61d.mwjdj.cn
http://SWst3nSu.mwjdj.cn
http://YWDCgvmv.mwjdj.cn
http://ijF839kH.mwjdj.cn
http://jUebxHRh.mwjdj.cn
http://PCOMyBTZ.mwjdj.cn
http://Z8L45xUa.mwjdj.cn
http://SPms1e2h.mwjdj.cn
http://8MW9XjGc.mwjdj.cn
http://webNIQX5.mwjdj.cn
http://eP8VcKms.mwjdj.cn
http://NtFIG01r.mwjdj.cn
http://9LwhYfem.mwjdj.cn
http://2PoXXpno.mwjdj.cn
http://zvEXzNPr.mwjdj.cn
http://FX2al71U.mwjdj.cn
http://qKJeO8po.mwjdj.cn
http://www.dtcms.com/a/368441.html

相关文章:

  • 在本地使用Node.js和Express框架来连接和操作远程数据库
  • Linux应用(2)——标准IO
  • 面试官问:你选择这份工作的动机是什么?
  • 大型语言模型SEO(LLM SEO)完全手册:驾驭搜索新范式
  • Onlyoffice集成与AI交互操作指引(Iframe版)
  • 前端视觉交互设计全解析:从悬停高亮到多维交互体系(含代码 + 图表)
  • 【基础组件】手撕 MYSQL 连接池(C++ 版本)
  • 【FastDDS】Layer Transport ( 01-overview )
  • 算法备案全流程-纯干货
  • Linux 进程信号的产生
  • 【华为Mate XTs 非凡大师】麒麟芯片回归:Mate XTs搭载麒麟9020,鸿蒙5.1体验新境界
  • Swift 解题:LeetCode 372 超级次方(Super Pow)
  • 深入理解 JVM 字节码文件:从组成结构到 Arthas 工具实践
  • C# 阿里云 OSS 图片上传步骤及浏览器查看方法
  • JVM新生代和老生代比例如何设置?
  • 基于OpenGL封装摄像机类:视图矩阵与透视矩阵的实现
  • MySQL 8.0.36 主从复制完整实验
  • 无需bootloader,BootROM -> Linux Kernel 启动模式
  • 【Vue3+TypeScript】H5项目实现企业微信OAuth2.0授权登录完整指南
  • 为什么MySQL可重复读级别不能完全避免幻读
  • Gradle Task 进阶:Task 依赖关系、输入输出、增量构建原理
  • 串口通信基础知识
  • webshell及冰蝎双击无法打开?
  • Doris 数据仓库例子
  • 从零构建企业级LLMOps平台:LMForge——支持多模型、可视化编排、知识库与安全审核的全栈解决方案
  • 如何根据Excel数据表生成多个合同、工作证、录取通知书等word文件?
  • Highcharts 数据源常见问题解析:连接方式、格式处理与性能优化指南
  • T06_RNN示例
  • 【Android】Room数据库的使用
  • CoolGuard风控系统配置评分卡、权重策略|QLExpress脚本