跳至主要內容

分布式选举:国不可一日无君

AruNi_Lu分布式技术分布式协调与同步约 2953 字大约 10 分钟2023年6月10日

本文内容

前言

谈到分布式,那必定涉及到集群了,因为分布式无非就是加几台机器,那么这一群机器就组成了一个集群。集群中的各台机器,也叫作节点。

那集群中的节点都是怎么协同、怎么管理的呢?这就需要一个 Leader 来负责调度和管理其他节点,以达到集群中的数据一致性

在分布式中,这个 Leader 被称为 主节点,而选举 Leader 的过程,就叫作 分布式选举

1. 为什么要有分布式选举?

在分布式中,主节点负责调度、管理和协调其他节点,在主节点的管理下,能保证集群正确有序的运行。

试想一下,如果主节点一旦故障,其他节点应该如何应对?就好比皇上驾崩,天下大乱一样。这就像 “国不可一日无君”,在分布式中称为 “集群不可一刻无主”。

所以就需要有一个机制,在主节点故障后,能在其他节点中选举出一个新的主节点,以保证集群能正常的运行,这个过程就是 分布式选举

目前常见的分布式选举方法有:

2. Bully 算法:长者为大

2.1 基本概念

Bully 算法是一种以 “长者” 为大的集群选主算法,即在所有活着的节点中,选择 ID 最大的作为主节点

Bully('bʊli),翻译为横行霸道、仗势欺人。

在 Bully 算法中,需要使用 3 种消息:

由于 Bully 算法的选举原则是 ID 最大,因此集群中的 每个节点都要知道其他节点的 ID

当主节点故障或与其他节点失去联系后,或者有更大 ID 的节点加入集群,才会重新选主。节点会定期向主节点发送 心跳消息 来检测它是否在线,若一段时间后没有收到主节点的回复,则认为该主节点已经故障,则会发起选举。

2.2 选举过程

一次 Bully 算法选举的过程如下:

  1. 每个节点判断自己 ID 是否为集群中的最大值:
    • 如果是则向其他节点发送 Victory 消息宣誓主权;
    • 如果不是则向比自己大的节点发送 Election 消息;
  2. 若节点收到比自己 ID 小的 Election 消息,则回复 Alive 消息,告诉它我比你大,你不可能成为主节点;
  3. 在给定时间范围内:
    • 节点没有收到 Alive 消息,则认为自己成为主节点,并向其他节点发送 Victory 消息宣誓主权;
    • 若收到比自己 ID 大的 Alive 消息,则等待其他节点发送 Victory 消息。

举个例子,假设原来集群的主节点是 4,现在出现了故障,其他节点通过心跳检测发现主节点已经故障,触发了选举,则 Bully 算法的选举过程如下:

2.3 Bully 优缺点

优点:

缺点:

解决方案

主节点假死的解决:

  • 让集群中一半以上的节点都认为主节点故障了,才开始新的选举。

脑裂问题的解决:

  • 向比自己 ID 大的节点发送 Election 消息后,如果没有收到对应的 Alive 回复,则发送一次 探活消息,以确保比自己 ID 大的节点是否真的已经故障了。

3. Raft 算法:民主投票

3.1 基本概念

Raft 算法 的核心思想是 通过投票选举,最后以少数服从多数来确定主节点。就跟我们平时进行民主投票选举什么书记一样。

在 Raft 算法中,集群节点有 3 种角色:

在 Raft 算法中,选举后的 Leader 节点是有任期的,到了后就需要重新选举。当然了,如果 Leader 节点故障,则会马上发起选举。

3.2 选举过程

Raft 选举分为下面几步:

  1. 初始化时,所有节点均为 Follower 状态;
  2. 开始选主时,所有节点变为 Candidate 状态,并向其他节点发起选举请求;
  3. 其他节点按照收到请求的先后顺序,回复是否同意其成为主。注意:每一轮的选举中,一个节点只能投一次票
  4. 若发起选举请求的节点获得超过一半的投票,则可成为主节点。
    • 此时该节点的状态变为 Leader,其他节点则由 Candidate 降为 Follower;
    • Leader 节点与 Follower 节点会定期发送心跳包来检测存活状态。
  5. Leader 节点任期(term)到后,状态降为 Follower,开始进入新一轮的选主。

可以发现,Raft 算法在正常工作期间只有 Leader 和 Followers,Candidate 只有在选举时才出现。

Raft 算法将时间分为一段一段的任期(term),每段 term 的开始都是选举,然后以选举是否成功来觉得该 term 是否继续:

img

在选举过程中,各个状态的转变如下:

image-20230610171414435

3.3 Raft 优缺点

优点:

缺点:

4. ZAB 算法:具备优先级的民主投票

4.1 基本概念

ZAB(Zookeeper Atomic Broadcast,Zookeeper 原子广播)选举算法是为 Zookeeper 实现分布式协调而设计的,用于保证 Zookeeper 在分布式环境下的一致性和可靠性。

相比于 Raft 的投票机制,ZAB 添加了节点 ID 和数据 ID 作为参考进行选主。节点 ID 和数据 ID 越大,说明数据越新,越优先成为主

  • 节点 ID 用来标识节点的顺序,单调递增,ID 越大表示加入集群的事件越晚;
  • 数据 ID 用来标识数据的写操作顺序,每个写操作都会将数据 ID +1,ID 越大表示数据越新。

在 ZAB 算法选举时,集群节点有 3 种角色:

在选举过程中,节点拥有 4 种状态:

投票过程中,每个节点都有一个唯一的三元组

ZAB 选举算法的核心是 “少数服从多数,ID 大的节点优先”,选举时通过 (vote_id、vote_zxID) 来表明投票给哪个节点。

ZAB 选主原则:server_zxID 最大者成为 Leader,若 server_zxID 相同,则 server_id 最大者成为 Leader

4.2 选举过程

以 3 个 Server(节点)的集群为例,下面来看看 ZAB 算法的选主过程:

  1. 系统启动时,3 个服务器都是第一轮投票(epoch=1),且无操作数据(zxID=0),此时每台服务器都推选自己成为主。将投票信息 <epoch, vote_id, vote_zxID> 广播出去:

    img

  2. 根据选主规则,由于 3 个服务器的 epoch、zxID 都相同,因此将 server_id 较大者推选为主。所以 Server 1 和 Server 2 将 vote_id 改为 3,然后重新广播:

    img

  3. 所有服务器都推选了 Server 3,票数过半,因此它成为 Leader,处于 Leading 状态。此时向其他服务器发送心跳包并维护连接,然后 Server 1 和 2 处于 Following 状态:

    img

这样这一轮的选举就完成了。

4.3 ZAB 的优缺点

优点:

缺点:

5. 总结

在讲解了分布式选举的 3 种经典算法 Bully、Raft、ZAB 后,下面从消息传递内容、选举机制和选举过程,对它们进行一个简单的对比:

img

注:性能是根据算法的选举延迟、正确性、稳定性等特性来综合考量的。

LastTip

对于 “少数服从多数” 的选举算法而言,一般集群中的节点数量会是奇数个,是为了避免选举过程中出现平票而重新进行多次选举。