1. 背景介绍
Apache ZooKeeper 是分布式系统中常用的协调服务框架,提供配置管理、命名服务、分布式锁和集群管理等功能。
在一个 ZooKeeper 集群中,有三类角色:
Leader:负责事务请求的处理和集群内数据同步。
Follower:处理非事务请求,参与投票选举,接受 Leader 的同步。
Observer:不参与投票,仅作为读请求的分流节点。
ZooKeeper 的核心目标是保证数据一致性。因此,当 Leader 节点宕机或网络分区时,ZooKeeper 必须通过选举算法快速选出新的 Leader,保证系统继续正常运行。
2. ZooKeeper 的选举触发条件
选举算法会在以下场景触发:
集群启动时,没有 Leader,需要选举。
Leader 节点宕机或失联,需重新选举。
节点间网络分区,部分节点失去对 Leader 的感知。
3. 选举算法的演进
ZooKeeper 核心启用三种选举算法:
3.1 基于 UDP 的 LeaderElection(早期版本)
使用 UDP 广播进行投票交换。
存在可靠性问题,容易丢包,已经逐步淘汰。
3.2 基于 TCP 的 LeaderElection
改用 TCP 保证消息可靠传输。
选举效率比 UDP 稳定,但实现较艰难。
3.3 FastLeaderElection(目前主流)
Hadoop/ZooKeeper 3.4 之后的默认算法。
基于 TCP 进行投票,支持epoch(逻辑时钟) 和 ZXID(事务 ID) 的比较。
高效、健壮,能够迅速收敛到一个新的 Leader。
4. FastLeaderElection 算法原理
ZooKeeper 的选举过程依赖三个关键信息:
myid:节点 ID,每个节点唯一。
ZXID:事务日志 ID,反映节点材料最新程度。
epoch:逻辑时钟,区分不同轮次的选举。
核心投票规则:
优先比较 epoch(逻辑时钟),epoch 越大越新。
如果 epoch 相同,比较ZXID,数据更新的节点更优。
若是 ZXID 也相同,比较myid,ID 较大的节点胜出。
选举步骤:
所有节点进入LOOKING状态,发起投票。
每个节点先投自己一票,广播给集群。
收到其他投票后,比较 epoch/ZXID/myid,更新自己的投票。
当某个候选人获得超过半数节点的帮助时,该候选人成为新的 Leader。
其他节点更新为FOLLOWING/OBSERVING状态,达成选举。
5. 举例说明
假设一个 ZooKeeper 集群中有 5 个节点:
节点 1:ZXID=5
节点 2:ZXID=8
节点 3:ZXID=6
节点 4:ZXID=8
节点 5:ZXID=7
选举过程:
初始时,所有节点都投自己。
节点间交换投票后,发现 ZXID 最大的是 8(节点 2 和 4)。
ZXID 相同的情况下,比较 myid,节点 4 的 ID 大于节点 2。
节点 4 获得超过半数的支持,成为新的 Leader。
6. ZooKeeper 选举算法的优缺点
优点:
快速收敛:利用过半原则,保证最终一致性。
高可靠性:基于 TCP 通信,减少丢包问题。
数据安全:优先选择数据最新的节点作为 Leader。
缺点:
在大规模集群中,选举过程可能带来额外的网络开销。
网络分区时可能导致脑裂,需要依赖过半原则避免。
7. 总结
保证集群高可用性的核心机制。就是ZooKeeper 的选举算法
早期 LeaderElection:基于 UDP,不可靠。
TCP LeaderElection:基于 TCP,改进可靠性。
FastLeaderElection:目前主流,基于 epoch + ZXID + myid 的比较规则,高效可靠。
一句话总结:
ZooKeeper 通过 FastLeaderElection 算法,确保在 Leader 故障时能快速选出新的 Leader,从而保证集群的一致性和高可用性。