选举的作用就是选出一个主节点,由它来协调和管理其他节点,以保证集群有序运行和节点间数据的一致性。
目前常见的分布式选举算法:
基于序号选举的算法( Bully 算法)、
多数派算法(Raft 算法、ZAB 算法)
Bully 算法是一种霸道的集群选主算法,因为它的选举原则是“长者”为大,即在所有活着的节点中,选取 ID 最大的节点作为主节点。
优点:谁的id大谁就是老大,其他节点必须服从,选举速度快、算法复杂度低、简单易实现。
缺点:每个节点都要保存其他所有节点的id,因此额外信息存储较多
使用场景:
MongoDB 的副本集故障转移功能。MongoDB 的分布式选举中,采用节点的最后操作时间戳来表示 ID,时间戳最新的节点其 ID 最大,也就是说时间戳最新的、活着的节点是主节点。
Raft 算法是典型的多数派投票选举算法,其选举机制与我们日常生活中的民主投票机制类似,核心思想是“少数服从多数”。也就是说,Raft 算法中,获得投票最多的节点成为主。
采用 Raft 算法选举,集群节点的角色有 3 种:
Raft 选举的流程,可以分为以下几步:
初始化时,所有节点均为 Follower 状态。
开始选主时,所有节点的状态由 Follower 转化为 Candidate,并向其他节点发送选举请求。
其他节点根据接收到的选举请求的先后顺序,回复是否同意成为主。这里需要注意的是,在每一轮选举中,一个节点只能投出一张票。
若发起选举请求的节点获得超过一半的投票,则成为主节点,其状态转化为 Leader,其他节点的状态则由 Candidate 降为 Follower。Leader 节点与 Follower 节点之间会定期发送心跳包,以检测主节点是否活着。
当 Leader 节点的任期到了,即发现其他服务器开始下一轮选主周期时,Leader 节点的状态由 Leader 降级为 Follower,进入新一轮选主。
优点:Raft 算法具有选举速度快、算法复杂度低、易于实现的
缺点:它要求系统内每个节点都可以相互通信,且需要获得过半的投票数才能选主成功,因此通信量大。
ZAB(ZooKeeper Atomic Broadcast)
ZAB选举算法是为 ZooKeeper 实现分布式协调功能而设计的。
相较于 Raft 算法的投票机制,ZAB 算法增加了通过节点 ID 和数据 ID 作为参考进行选主,节点 ID 和数据 ID 越大,表示数据越新,越优先成为主。
相比较于 Raft 算法,ZAB 算法尽可能保证数据的最新性。
所以,ZAB 算法可以说是对 Raft 算法的改进。
使用 ZAB 算法选举时,集群中每个节点拥有 3 种角色:
选举过程中,集群中的节点拥有 4 个状态:
优点:但该算法选举稳定性比较好,当有新节点加入或节点故障恢复后,会触发选主,但不一定会真正切主,除非新节点或故障后恢复的节点数据 ID 和节点 ID 最大,且获得投票数过半,才会导致切主。
缺点:采用广播方式发送信息,若节点中有 n 个节点,每个节点同时广播,则集群中信息量为 n*(n-1) 个消息,容易出现广播风暴;
且除了投票,还增加了对比节点 ID 和数据 ID,这就意味着还需要知道所有节点的 ID 和数据 ID,所以选举时间相对较长。

