【大数据哔哔集20210124】有人问我Kafka Leader选举?我真没慌

一条消息只有被ISR中全部Follower都从Leader复制过去才会被认为已提交。这样就避免了部分数据被写进了Leader,还没来得及被任何Follower复制就宕机了,而形成数据丢失。而对于Producer而言,它能够选择是否等待消息commit,这能够经过request.required.acks来设置。这种机制确保了只要ISR中有一个或者以上的follower,一条被commit的消息就不会丢失。算法

什么是ISR?参考这里:【大数据哔哔集20210123】别问,问就是Kafka高可靠性能

有一个很重要的问题是当Leader宕机了,怎样在Follower中选举出新的Leader,由于Follower可能落后不少或者直接crash了,因此必须确保选择最新的Follower做为新的Leader。一个基本的原则就是,若是Leader不在了,新的Leader必须拥有原来的Leader commit的全部消息。这就须要作一个折中,若是Leader在一个消息被commit前等待更多的Follower确认,那么在它挂掉以后就有更多的Follower能够成为新的Leader,但这也会形成吞吐率的降低。大数据

一种很是经常使用的选举Leader的方式是“少数服从多数“,Kafka并非采用这种方式。这种模式下,若是咱们有2f+1个副本,那么在commit以前必须保证有f+1个replica复制完消息,同时为了保证能正确选举出新的Leader,失败的副本数不能超过f个。这种方式有个很大的优点,系统的延迟取决于最快的几台机器,也就是说好比副本数为3,那么延迟就取决于最快的那个Follower而不是最慢的那个。“少数服从多数”的方式也有一些劣势,为了保证Leader选举的正常进行,它所能容忍的失败的Follower数比较少,若是要容忍1个Follower挂掉,那么至少要3个以上的副本,若是要容忍2个Follower挂掉,必需要有5个以上的副本。也就是说,在生产环境下为了保证较高的容错率,必需要有大量的副本,而大量的副本又会在大数据量下致使性能的急剧降低。这种算法更多用在Zookeeper这种共享集群配置的系统中而不多在须要大量数据的系统中使用的缘由。HDFS的HA功能也是基于“少数服从多数”的方式,可是其数据存储并非采用这样的方式。ui

实际上,Leader选举的算法很是多,好比Zookeeper的Zab、Raft以及Viewstamped Replication。而Kafka所使用的Leader选举算法更像是微软的PacificA算法。blog

Kafka在Zookeeper中为每个Partition动态的维护了一个ISR,这个ISR里的全部replica都跟上了Leader,只有ISR里的成员才能有被选为Leader的可能(unclean.leader.election.enable=false)。在这种模式下,对于f+1个副本,一个Kafka Topic能在保证不丢失已经commit消息的前提下容忍f个副本的失败,在大多数使用场景下,这种模式是十分有利的。事实上,为了容忍f个副本的失败,“少数服从多数”的方式和ISR在commit前须要等待的副本的数量是同样的,可是ISR须要的总的副本的个数几乎是“少数服从多数”的方式的一半。token

上文提到,在ISR中至少有一个Follower时,Kafka能够确保已经commit的数据不丢失,但若是某一个Partition的全部replica都挂了,就没法保证数据不丢失了。这种状况下有两种可行的方案:ci

  • 等待ISR中任意一个replica“活”过来,而且选它做为Leader
  • 选择第一个“活”过来的replica(并不必定是在ISR中)做为Leader

这就须要在可用性和一致性当中做出一个简单的抉择。若是必定要等待ISR中的replica“活”过来,那不可用的时间就可能会相对较长。并且若是ISR中全部的replica都没法“活”过来了,或者数据丢失了,这个Partition将永远不可用。选择第一个“活”过来的replica做为Leader,而这个replica不是ISR中的replica,那即便它并不保障已经包含了全部已commit的消息,它也会成为Leader而做为Consumer的数据源。默认状况下,Kafka采用第二种策略,即unclean.leader.election.enable=true,也能够将此参数设置为false来启用第一种策略。get

unclean.leader.election.enable这个参数对于leader的选举、系统的可用性以及数据的可靠性都有相当重要的影响。下面咱们来分析下几种典型的场景。it

file

若是上图所示,假设某个Partition中的副本数为3,replica-0, replica-1, replica-2分别存放在Broker0, Broker1和Broker2中。AR=(0,1,2),ISR=(0,1)。
设置request.required.acks=-1, min.insync.replicas=2,unclean.leader.election.enable=false。这里将Broker0中的副本也称之为Broker0起初Broker0为Leader,Broker1为Follower。io

  • 当ISR中的replica-0出现crash的状况时,Broker1选举为新的Leader[ISR=(1)],由于受min.insync.replicas=2影响,write不能服务,可是read能继续正常服务。此种状况恢复方案:
  1. 尝试恢复(重启)replica-0,若是能起来,系统正常;2. 若是replica-0不能恢复,须要将min.insync.replicas设置为1,恢复write功能。
  • 当ISR中的replica-0出现crash,紧接着replica-1也出现了crash, 此时[ISR=(1),leader=-1],不能对外提供服务,此种状况恢复方案:
  1. 尝试恢复replica-0和replica-1,若是都能起来,则系统恢复正常;
  1. 若是replica-0起来,而replica-1不能起来,这时候仍然不能选出Leader,由于当设置unclean.leader.election.enable=false时,leader只能从ISR中选举,当ISR中全部副本都失效以后,须要ISR中最后失效的那个副本能恢复以后才能选举Leader,即replica-0先失效,replica-1后失效,须要replica-1恢复后才能选举Leader。保守的方案建议设置unclean.leader.election.enable=true,可是这样会有丢失数据的状况发生,这样能够恢复read服务。一样须要将min.insync.replicas设置为1,恢复write功能;
  2. replica-1恢复,replica-0不能恢复,这个状况上面遇到过,read服务可用,须要将min.insync.replicas设置为1,恢复write功能;
  3. replica-0和replica-1都不能恢复,这种状况能够参考情形2.
  • 当ISR中的replica-0,replica-1同时宕机,此时[ISR=(0,1)],不能对外提供服务,此种状况恢复方案:尝试恢复replica-0和replica-1,当其中任意一个副本恢复正常时,对外能够提供read服务。直到2个副本恢复正常,write功能才能恢复,或者将将min.insync.replicas设置为1。

欢迎关注,《大数据成神之路》系列文章

欢迎关注,《大数据成神之路》系列文章

欢迎关注,《大数据成神之路》系列文章

相关文章
相关标签/搜索