当前位置: 首页 > news >正文

kafka知识体系-kafka leader选举

本系列主要讲解kafka基本设计和原理分析,分如下内容:

  1. 基本概念
  2. 消息模型
  3. kafka副本同步机制
  4. kafka文件存储机制
  5. kafka数据可靠性和一致性保证
  6. kafka leader选举
  7. kafka消息传递语义
  8. Kafka集群partitions/replicas默认分配解析

kafka leader选举

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

有一个很重要的问题是当leader宕机了,怎样在follower中选举出新的leader,因为follower可能落后很多或者直接crash了,所以必须确保选择“最新”的follower作为新的leader。一个基本的原则就是,如果leader不在了,新的leader必须拥有原来的leader commit的所有消息。这就需要做一个折中,如果leader在表名一个消息被commit前等待更多的follower确认,那么在它挂掉之后就有更多的follower可以成为新的leader,但这也会造成吞吐率的下降。

有一个很重要的问题是当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功能也是基于“少数服从多数”的方式,但是其数据存储并不是采用这样的方式。

实际上,leader选举的算法非常多,比如Zookeeper的Zab、Raft以及Viewstamped Replication。而Kafka所使用的leader选举算法更像是微软的PacificA算法。

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

上文提到,在ISR中至少有一个follower时,Kafka可以确保已经commit的数据不丢失,但如果某一个partition的所有replica都挂了,就无法保证数据不丢失了。这种情况下有两种可行的方案:

  • 等待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来启用第一种策略。

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

719892-20180627212431940-1513014277.png

如果上图所示,假设某个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。

1. 当ISR中的replica-0出现crash的情况时,broker1选举为新的leader[ISR=(1)]
因为受min.insync.replicas=2影响,write不能服务,但是read能继续正常服务。此种情况恢复方案:

  • 尝试恢复(重启)replica-0,如果能起来,系统正常;
  • 如果replica-0不能恢复,需要将min.insync.replicas设置为1,恢复write功能。

2. 当ISR中的replica-0出现crash,紧接着replica-1也出现了crash, 此时[ISR=(1),leader=-1]

不能对外提供服务,此种情况恢复方案:

  • 尝试恢复replica-0和replica-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功能;
  • replica-1恢复,replica-0不能恢复,这个情况上面遇到过,read服务可用,需要将min.insync.replicas设置为1,恢复write功能;
  • replica-0和replica-1都不能恢复,这种情况可以参考情形2.

3. 当ISR中的replica-0, replica-1同时宕机,此时[ISR=(0,1)]

不能对外提供服务,此种情况恢复方案:尝试恢复replica-0和replica-1,当其中任意一个副本恢复正常时,对外可以提供read服务。直到2个副本恢复正常,write功能才能恢复,或者将将min.insync.replicas设置为1。


关于作者
爱编程、爱钻研、爱分享、爱生活
关注分布式、高并发、数据挖掘
如需捐赠,请扫码
sqm.jpg

转载于:https://www.cnblogs.com/aidodoo/p/8888628.html

相关文章:

  • 数据概述
  • winform控件大全
  • C#如何在VS2015 2017版本中编写WPF UI界面引入第三方SVG图形
  • 设计模式体会
  • 函数参数选项的处理getopt getopt_long getopt_long_only
  • eclipse 配置多个tomcat
  • io流2
  • 图文剖析自己定义View的绘制(以自己定义滑动button为例)
  • 项目策划的原则
  • zabbix使用web界面设置邮件报警
  • 大牛地址
  • 查询MySQL某字段相同值得重复数据
  • js 数字转换成带逗号的显示方式
  • Apache 修改登录账户
  • 2017-2018工作总结(更新中)
  • [译]如何构建服务器端web组件,为何要构建?
  • docker容器内的网络抓包
  • Docker下部署自己的LNMP工作环境
  • IOS评论框不贴底(ios12新bug)
  • JavaWeb(学习笔记二)
  • JS学习笔记——闭包
  • Object.assign方法不能实现深复制
  • Redux 中间件分析
  • Vue--数据传输
  • 算法之不定期更新(一)(2018-04-12)
  • 异步
  • 选择阿里云数据库HBase版十大理由
  • ​力扣解法汇总1802. 有界数组中指定下标处的最大值
  • !!Dom4j 学习笔记
  • #图像处理
  • $分析了六十多年间100万字的政府工作报告,我看到了这样的变迁
  • (C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令...
  • (pytorch进阶之路)CLIP模型 实现图像多模态检索任务
  • (二)pulsar安装在独立的docker中,python测试
  • (二)构建dubbo分布式平台-平台功能导图
  • (翻译)Quartz官方教程——第一课:Quartz入门
  • (论文阅读22/100)Learning a Deep Compact Image Representation for Visual Tracking
  • (强烈推荐)移动端音视频从零到上手(上)
  • (原創) 如何使用ISO C++讀寫BMP圖檔? (C/C++) (Image Processing)
  • .libPaths()设置包加载目录
  • .NET/C# 使用 #if 和 Conditional 特性来按条件编译代码的不同原理和适用场景
  • /usr/bin/python: can't decompress data; zlib not available 的异常处理
  • [《百万宝贝》观后]To be or not to be?
  • [AIGC 大数据基础]hive浅谈
  • [ASP.NET MVC]Ajax与CustomErrors的尴尬
  • [bzoj2957]楼房重建
  • [Grafana]ES数据源Alert告警发送
  • [HTML]Web前端开发技术18(HTML5、CSS3、JavaScript )HTML5 基础与CSS3 应用——喵喵画网页
  • [java] 23种设计模式之责任链模式
  • [Java]深入剖析常见排序
  • [javascript]Tab menu实现
  • [Kubernetes]2. k8s集群中部署基于nodejs golang的项目以及Pod、Deployment详解
  • [moka同学笔记]yii表单dropdownlist样式
  • [Oh My C++ Diary]带参数的main()函数
  • [python] 过年燃放烟花