4. 协同升级协议:两阶段提交(2PC)、三阶段提交(3PC)、Paxos/Raft协议

好,咱们进入正题。多分区协同升级,说白了就是让一堆节点步调一致地完成升级。这可不是件容易事。我早年做金融系统时,就吃过这个亏——升级到一半,某个节点挂了,整个集群状态变得不三不四。所以,协议选型是重中之重。

今天咱们聊三个经典协议:2PC、3PC,还有Paxos和Raft。它们各有各的脾气,也各有各的适用场景。

4.1 两阶段提交(2PC)—— 简单但脆弱

2PC 是最直观的协议。我习惯把它比作「班长收作业」:先问大家写没写完,然后统一说「交」。整个过程分两步:

  • 第一阶段(投票阶段):协调者问所有参与者:「能提交吗?」参与者回答 Yes 或 No。
  • 第二阶段(提交阶段):如果所有人都说 Yes,协调者通知大家「提交」。但凡有一个人说 No,就通知所有人「回滚」。

听起来很简单对吧?但问题也出在这里。

⚠️ 核心痛点:单点阻塞与脑裂风险

协调者一旦挂了,所有参与者都得傻等。我曾经在项目中遇到过这种情况:协调者发完「准备提交」的消息后宕机了,所有参与者都持有锁资源,业务直接卡死半小时。你想想看,这在线上环境有多致命。

另外,2PC 是同步阻塞协议。参与者收到「准备」指令后,必须把资源锁住,直到收到最终决定。这在高并发场景下,简直就是性能杀手。

💡 我的建议

2PC 只适合节点少、网络稳定、对一致性要求极高的场景。比如,你只有两三个数据库实例要做分布式事务,用 2PC 没问题。但超过 5 个节点,我劝你慎重。

4.2 三阶段提交(3PC)—— 解决阻塞,但引入新问题

3PC 是 2PC 的改良版。它多了一个阶段,目的是减少阻塞时间。流程是这样的:

  1. CanCommit(询问阶段):协调者问大家:「能不能提交?」参与者只需回答「能」或「不能」,不需要锁资源。
  2. PreCommit(预提交阶段):如果所有人都说「能」,协调者发「预提交」指令。参与者开始锁资源,并执行事务,但不提交。
  3. DoCommit(提交阶段):协调者确认所有参与者都预提交成功后,发「正式提交」指令。

嗯,这里要注意:3PC 引入了超时机制。参与者在等待协调者指令时,如果超时了,会自动提交。这解决了 2PC 的「死等」问题。

但说实话,3PC 在实际生产中用得并不多。为什么?因为它引入了新的脑裂风险。举个例子:

一个真实的坑

我曾经在测试环境搭过 3PC 集群。网络抖动时,部分参与者超时自动提交了,但协调者后来发的是「回滚」指令。结果就是:一部分节点提交了,一部分回滚了。数据直接不一致。你说这找谁说理去?

所以,3PC 虽然解决了阻塞问题,但牺牲了一致性。在大多数分布式系统中,我们宁愿阻塞,也不愿数据不一致。

4.3 Paxos 与 Raft —— 真正能打的共识协议

好了,聊点真正能用的。Paxos 和 Raft 是工业界最主流的共识协议。它们的目标是:在部分节点故障的情况下,依然能达成一致。

4.3.1 Paxos —— 理论上的王者

Paxos 是 Leslie Lamport 提出的。说实话,这协议理解起来有点绕。我当年啃了三天才搞明白。它的核心思想是「多数派同意」:

  • 提议者(Proposer)提出一个值。
  • 接受者(Acceptor)投票。
  • 超过半数接受者同意,这个值就被选定。

Paxos 有两个阶段:

  1. Prepare 阶段:提议者生成一个提案编号 N,发给所有接受者。接受者承诺:不再接受编号小于 N 的提案。
  2. Accept 阶段:提议者收到半数以上承诺后,发送提案值。接受者如果没违反承诺,就接受这个值。

你看,Paxos 通过编号机制解决了「活锁」问题。但它的实现复杂度太高了。我记得有个笑话:Paxos 的论文比它的实现还要出名。嗯,确实如此。

💡 个人经验

除非你是做底层基础设施的,否则别自己实现 Paxos。直接用现成的实现,比如 Google 的 Chubby、ZooKeeper 的 ZAB 协议,它们都是 Paxos 的变种。

4.3.2 Raft —— 工程上的首选

Raft 是 Paxos 的简化版。它的设计目标就是「可理解性」。说白了,就是让普通工程师也能看懂、能实现。

Raft 把共识问题拆成了三个子问题:

子问题 说明
领导者选举 集群中选出一个 Leader,负责处理所有写请求
日志复制 Leader 把操作日志复制到所有 Follower
安全性 保证日志的一致性,不会出现覆盖或丢失

Raft 的选举机制很有意思。每个节点有超时时间,谁先超时谁发起选举。得票过半的成为 Leader。Leader 定期发心跳维持地位。如果 Leader 挂了,其他节点超时后重新选举。

我强烈推荐 Raft。为什么?因为它在工程上太友好了。我参与过一个分布式存储项目,就是用 Raft 做元数据同步。从选型到上线,只花了两周。换成 Paxos,光理解协议就得一个月。

避坑指南:Raft 的日志复制

我曾经犯过一个错:在日志复制时,没有处理「网络分区」的情况。结果 Leader 在少数派分区里,写入了数据,但多数派分区选举了新 Leader。等分区恢复后,旧 Leader 的数据被覆盖了。嗯,这其实是 Raft 协议设计好的,但如果你没理解「任期号」和「日志索引」的机制,很容易踩坑。

4.4 协议对比与选型建议

好了,咱们总结一下。这几个协议各有优劣,我习惯用一张表来对比:

协议 一致性 可用性 性能 实现复杂度 适用场景
2PC 强一致 低(协调者单点) 低(同步阻塞) 小规模分布式事务
3PC 弱一致(脑裂风险) 较少使用
Paxos 强一致 底层基础设施
Raft 强一致 大多数分布式系统

我个人建议:

  • 如果你在做微服务间的分布式事务,且节点数少于 5 个,用 2PC 加补偿机制(比如 Saga 模式)。
  • 如果你在做分布式存储、配置中心、服务发现,直接上 Raft。别犹豫。
  • 至于 3PC,嗯,我建议你直接跳过。它解决的问题不够痛,引入的问题却不少。
  • Paxos 嘛,除非你是大神,或者公司有专门的分布式团队,否则别碰。

最后说一句:协议只是工具,不是目的。我们的目标是让系统在升级过程中保持稳定、一致、可用。选对协议,事半功倍;选错了,后面全是坑。