4. 分布式一致性协议:Paxos、Raft、Zab协议的原理与对比,Leader选举机制

说到分布式系统,一致性协议是绕不开的硬骨头。我刚开始接触这块时,也被Paxos搞得晕头转向。后来在项目中摸爬滚打,才慢慢理清了脉络。今天咱们就聊聊这三个主流协议:Paxos、Raft和Zab。

4.1 为什么需要一致性协议?

说白了,分布式系统里最怕的就是「脑裂」。多个节点各说各话,数据乱成一锅粥。你想想看,一个集群里三个节点,A说值是1,B说值是2,C说值是3——到底听谁的?

一致性协议就是来解决这个问题的。它保证所有节点最终达成一致,不会出现数据打架的情况。我在做电商订单系统时,就遇到过因为一致性没做好,导致同一个订单被重复发货的惨案...嗯,从那以后我对这块格外上心。

4.2 Paxos:祖师爷级别的协议

Paxos是Lamport大神在1990年提出的。说实话,它很强大,但也很难懂。我读原论文时,Lamport用了一个古希腊议会的故事来比喻,看得我云里雾里。

4.2.1 Paxos的核心角色

  • Proposer(提议者):负责提出提案
  • Acceptor(接受者):负责投票表决
  • Learner(学习者):负责学习最终结果

4.2.2 Paxos的两阶段提交

Paxos的核心是两阶段提交:Prepare阶段和Accept阶段。

// 伪代码示例:Paxos Prepare阶段
Proposer发送Prepare(n)给所有Acceptor
Acceptor响应:
  - 如果n大于之前见过的任何编号,承诺不再接受小于n的提案
  - 返回已接受的最大编号提案(如果有)

// 伪代码示例:Paxos Accept阶段
Proposer收到多数派响应后,发送Accept(n, value)给所有Acceptor
Acceptor响应:
  - 如果没有收到更大的Prepare请求,则接受该提案

我个人习惯把Paxos理解成「先占坑,再填坑」。Prepare阶段就是占坑,告诉别人「这个编号我要了」;Accept阶段才是真正填内容。

关键点:Paxos保证安全性(Safety),但不保证活性(Liveness)。也就是说,它不会产生错误结果,但可能永远达不成一致——这就是著名的「活锁」问题。

4.3 Raft:更易理解的一致性协议

Raft是2013年提出的,目的就是让一致性协议变得好懂。我在项目中首选Raft,因为它真的「人话」多了。

4.3.1 Raft的三个状态

状态 说明 超时时间
Follower(跟随者) 被动响应请求 随机150-300ms
Candidate(候选者) 发起选举 选举超时
Leader(领导者) 处理所有客户端请求 心跳间隔

4.3.2 Leader选举机制

Raft的Leader选举是我见过最优雅的设计。它把问题拆成了几个小步骤:

  1. 触发选举:Follower收不到Leader心跳,超时后变成Candidate
  2. 发起投票:Candidate给自己投票,并请求其他节点投票
  3. 赢得选举:获得多数派(超过半数)投票的成为新Leader
  4. 任期机制:每个任期(Term)只有一个Leader

避坑指南:我曾经在部署Raft集群时,把节点数设成了偶数(4个)。结果网络分区时,两边各2个节点,谁也拿不到多数派,整个集群就挂了。记住:Raft集群节点数最好是奇数,3或5最常用。

4.4 Zab:ZooKeeper的原子广播协议

Zab是ZooKeeper使用的协议。它和Raft很像,但有一些关键区别。我在做配置中心时,底层就是Zab协议。

4.4.1 Zab的核心流程

  • 发现阶段:新Leader收集所有Follower的最新数据
  • 同步阶段:Leader把数据同步给所有Follower
  • 广播阶段:正常处理客户端请求,进行原子广播

4.4.2 Zab的Leader选举

Zab的选举机制和Raft不太一样。它使用「投票轮次+数据新鲜度」来决定谁当Leader。数据越新的节点,越有可能当选。

// Zab选举的投票比较规则
if (vote.epoch > current.epoch) {
    选择epoch更大的
} else if (vote.epoch == current.epoch) {
    if (vote.zxid > current.zxid) {
        选择zxid更大的(数据更新)
    } else {
        选择myid更大的(节点ID)
    }
}

注意:Zab的选举过程中,如果出现平局(两个节点数据一样新),会按照节点ID排序。所以节点ID越小,在平局时越有优势。我建议给核心节点分配较小的ID。

4.5 三大协议对比

特性 Paxos Raft Zab
易理解性
Leader选举 无固定Leader 强Leader 强Leader
数据顺序 不保证全局有序 保证全局有序 保证全局有序
典型应用 Chubby Etcd、Consul ZooKeeper
工程实现难度

4.6 我的选择建议

在实际项目中,我一般这样选:

  • 新项目:首选Raft。文档多、实现简单、社区活跃。Etcd和Consul都是好例子。
  • 需要强一致性且已有ZooKeeper:用Zab。别折腾,ZooKeeper很成熟。
  • 学术研究或特殊场景:才考虑Paxos。说实话,我工作这么多年,没自己实现过Paxos——太容易出bug了。

核心总结:一致性协议的本质就是「多数派决策」。不管是Paxos、Raft还是Zab,核心思想都一样:让多数节点说了算。区别在于实现细节和易用性。我个人觉得,选协议就像选工具——顺手最重要。

好了,这一章就聊到这儿。下一章咱们会深入Raft的日志复制和安全性,到时候我会分享一个我在生产环境遇到的Raft脑裂案例,保证让你印象深刻。