常见的分布式集群选举过程
2020-03-08 本文已影响0人
缄默的石头
1. Zookeeper
1.1 初始化启动Leader选举
前提:集群中要大于等于2台机器
- 发出投票
每个机器给自己投票,投票结构为(myid,zxid),然后将自己的投票发给其他的机器 - 接收投票
每台机器接收其他机器的投票,只比较和自己相同的epoch,并且是LOOKING状态的机器的投票 - 投票PK
3.1 进行zxid比对,以zxid较大的投票为准
3.2 如果zxid相同,以myid较大的投票为准
如果自己PK失败了,将自己的投票更新为选定的投票,然后重发出去;
如果自己PK胜利了,不用更新自己的投票,只需要重新香其他机器发出投票 - 统计投票
每次投票后,服务器都会统计所有的投票,判断是否有过半的机器接收到相同投票信息,当统计到有此情况时,认为Leader已经选出 - 改变服务器状态
一旦确定Leader,每个服务器会更新自己的状态,如果是Follower,状态变为Following;如果是Leader,状态变为Leading
1.2 崩溃恢复Leader选举
- 变更状态
当Leader挂了后,剩余的非Observer服务器会将自己的服务器状态变更为Looking,然后进入Leader选举流程 - 发出投票
- 接收投票
- 投票PK
- 统计投票
- 修改服务器状态
2. Redis
2.1 哨兵模式哨兵leader选举
目的:哨兵模式下当发现Master宕机后,哨兵要对主从进行自动切换,所以哨兵要选举出来一个leader来执行故障转移
原则:
- 每一个监视主服务器的哨兵都有资格成为领头哨兵
- 每一个设置纪元中领头哨兵确定后不能改变
- 在一个配置纪元中不管有没有选出领头哨兵,配置纪元+1
步骤:
- 哨兵拉票
拉票遵循先到先得原则:最先向目标sentinel发出设置要求的源sentinel将成为目标sentinel的局部领头sentinel,目标sentinel后续收到的设置要求会被拒绝; - 处理拉票
根据先到先得的原则,目标sentinel对设置要求做出响应,返回leader_runid和leader_epoch分别记录目标sentinel的局部领头sentinel的runId和配置纪元 - 检查拉票结果
源sentinel检查目标sentinel的响应结果,如果返回的配置纪元和自己的配置纪元相同,继续取出响应中的leader_runid,如果leader_runid和自己的runid相同,那么说明目标sentinel将自己设置为局部领头sentinel - 统计结果
如果某个sentinel被半数以上的sentinel设置为局部sentinel,那么这个sentinel将会成为这次配置纪元的领头sentinel - 重新选举
如果在给定时间内,没有选出领头的sentinel,那么各个sentinel将过一段时间再进行一次选举,知道选举出领头的sentinel
2.2 集群模式leader选举
背景:
当集群中大多数主服务节点将某一个主服务节点标记为下线,会在集群中广播主节点下线当消息,当一个从节点发现自己复制的主节点标记下线的时候要进行故障转移,从节点需要竞争为主节点
原则:
- 集群中的配置纪元是自增,初始值为0
- 当集群中的某个节点开始一次故障转移,集群的配置纪元+1
- 对于某一次配置纪元,主节点只有一次投票权,第一个向主节点要求投票的从节点获取选票
- 从节点的资格
4.1 过期的超时不执行。data_age = 当前时间点-上次master失联的时间点-超时时间,如果data_age > master到slave的ping间隔时间+超时时间乘以cluster_slave_validity_factor, 则认为过期。cluster_slave_validity_factor是一个配置项,cluster_slave_validity_factor 设置的越小越不容易触发failover。 - 从节点拉票的顺序
计算出一个延迟执行的时间failover_auth_time, failover_auth_time = 当前时间 + 500ms + random(0-500ms) + 当前slave的rank*1s, rank按已同步的offset计算,offset同步的越延迟,rank值越大,该slave 就越推迟触发failover的时间,以此来避免多个slave同时failover。只有当前时间到failover_auth_time的时间点才会执行failover。
步骤:
- 从节点拉票
主节点向集群广播一条CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST的消息,要求收到这条消息并具备投票权的主节点向这个从节点投票 - 主节点投票
当一个主节点收到消息并且有投票权并且还没有投给其他从节点,那么这个主节点将会给请求的从节点响应CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK的消息,表示主节点支持此从节点成为新的主节点 - 统计结果
每个从节点都会接收CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK消息,并根据消息数量的多少判断获取了多少主节点的支持;假设集群中有N个投票权的主节点,如果有一个从节点获取大于等于N/2+1张选票的时候,这个从节点当选为主节点 - 重新选举
如果在一个配置纪元中没有从节点获取足够多的选票,那么集群进入新的配置纪元,并再次选择,直到选出主节点为止
Kafka
3.1 Kafka Controller选举
目的:controller选举是为了在leader partition挂掉的时候能从ISR中选出一个副本作为新的leader partition,而controller就是执行这个故障转移的broker,它和其他的broker没有什么不一样
步骤:
- broker启动的时候,所有的broker都回去zookeeper上注册controller临时节点,只有一个broker可以注册成功,这个broker就是controller,follower broker会监听这个临时节点
- controller节点挂掉的时候,其他的broker会收到通知,重新竞争controller节点