分布式选举意义
为了协调与管理多个节点,会进行选举 Leader。
分布式选举算法
Bully 算法
- 节点角色:普通节点和主节点。最开始都为普通节点,平等的,都有成为主的权利。
- 重新选主时机:主节点故障或与其他节点失去联系时。
- 选举原则:所有可用节点中 ID 最大的节点作为主节点。
- 选举信息:
- Election 消息,用于发起选举;
- Alive 消息,对 Election 消息的应答;
- Victory 消息,竞选成功的主节点向其他节点发送的宣誓主权的消息。
- 选举过程:
- 每个节点判断自己 ID 是否是当前可用节点中 ID 最大的。
- 若是,则直接向其他节点发送 Victory 消息。
- 若不是,则向自己 ID 大的所有节点发送 Election 消息,并等待回复。
- 给定时间范围内,本节点没有收到其他节点的 Alive 信息,则认为自己成为主节点,并发送 Victory 消息。
- 若收到来自比自己 ID 大的节点 Alive 信息,则等待 Victory 信息。
- 若收到比自己 ID 小的节点发送的 Election 消息,则回复一个 Alive 消息,告知自己 ID 更大,重新选举。
- 每个节点判断自己 ID 是否是当前可用节点中 ID 最大的。
- 实际应用:MongoDB Replica Set 之前使用 Bully 算法,采用最后操作时间戳来表示 ID。(思考:时间戳选举可能存在节点时钟不一致的情况)
- 优点:选举速度更快、算法复杂度低、简单容易实现。
- 缺点:每个节点都需要有全局的节点信息,额外存储较多;其次,若更大 ID 的节点频繁进出集群,那么会频繁切主。
Raft 算法
- 节点角色:Leader、Candidate、Follower。
- 初始化时,所有节点都为 Follower。集群中第一个提出选主的节点会作为 Leader。
- Candidate,每个节点都可以成为候选者,只有先成为 Candidate 才能成为 Leader。
- 重新选主时机:主节点故障或与其他节点失去联系时、节点加入移出等时机。
- 选举原则:当 Follower 发现 Leader 失去联系时,会变为 Candidate 申请选主,并在获得多数票后成为 Leader。
- 选举信息:
- 略
- 选举过程:
- 当 Follower 发现 Leader 失去联系时,会变为 Candidate 任期 +1 并向其他节点发送选举请求。
- 选举过程中,对于一个任期的选举只能投一张票。
- 若选举请求的任期大于等于自己的任期,则会同意最先来的选举请求。任期小于自己的任期,则拒绝。
- 若 Candidate 一轮选举中获得多数票,则成为 Leader,其他均变为 Follower。
- 若 Candidate 一轮选举中没有获得多数票,则会重新发起选举。
- 若 Follower 一轮选举的超时时间内没收到 Leader 心跳,或 Candidate 投票请求,则变为 Candidate 发起选主。
- 同时,若 Leader 收到其他节点的选主请求,则会转变为 Follower,进入选主投票。
- 实际应用:Kafka、ETCD 等。
- 优点:选举速度快、算法复杂度低、易于实现。
- 缺点:每个节点相互通信,且票数过半才能成功,通信量大;全部理解困难。
更详细的 Raft 算法介绍参考:分布式共识:Raft。
ZAB 算法
- 节点角色:
- 角色:Leader 主节点、Follower 跟随者、Observer 观察者(无投票权)。
- 状态:Looking 状态(认为集群无 Leader,自己进入选举状态)、Leading 状态、Following 状态、Observing 状态。
- 重新选主时机:新节点加入、故障恢复、Leader 故障。
- 选举原则:每个节点会有一个三元祖(server_id, server_zxID, epoch),含义为:本节点唯一 ID、本节点数据 ID、当前选举轮数。“少数服从多数,ID 大的节点优先成为主”,优先级先 server_zxID 后 server_id。
- 选举信息:
- 申请选票信息 <epoch, vote_id, vote_zxID>
- 投票信息 <vote_id, vote_zxID>
- 选举过程:
- 每个节点广播申请选票信息 <epoch, vote_id, vote_zxID>
- 每个节点基于自己收到的选票信息,选择 ID 最大的节点作为投票项,然后广播出去。
- 被多数表决的节点成为 Leader,广播告知自己成为 Leader。
- 实际应用:ZooKeeper 等。
- 优点:性能高,无特殊需求;稳定性好,当新节点加入后故障恢复会触发选主,但不一定真正切主。
- 缺点:信息都是广播发送,出现广播风暴;选举需知道其他节点的数据和节点 ID 才能投票,选举时间长。
感觉了解的比较浅显。
扩展问题
分布式选举与一致性的关系
分布式选举算法是为了保证数据一致性的。
一个集群出现双主的原因
一个集群中出现双主,一般是网络故障导致,比如网络分区导致的情况。
出现双主的期间,如果双主均提供服务,可能会导致集群中数据不一致。所以,需要根据业务对数据不一致的容忍度来决定是否允许双主情况下提供服务。
如果单 Leader 成为性能瓶颈怎么办
当 Leader 成为性能瓶颈的时候,可以考虑多 Leader 服务。多 Leader 服务有两种场景:一种是去中心化的,这种采用最终一致性;一种是多个中心化集群协同处理,比如分层、集群联邦等方法。