当面试官问你啥是Kafka的选举时,抓住机会“吊打”他!

公众号后台回复 “ 资料 ” 

获取作者独家秘制学习资料

本文来源:朱小厮的博客

面试官在考查你Kafka知识的时候很可能会故弄玄虚的问你一下:Kafka中的选举时怎么回事?

除非问你具体的哪种选举,否则问这种问题的面试官多半也是对Kafka一知半解,这个时候就是“弄死”他的时候。当然如果你没有一定的知识储备,那么就是你被 “弄死” 的时候。

一般问这个问题,那么他肯定知道其中的一种,比如分区leader的选举。

所谓分区leader的选举就是当ISR中的leader副本歇菜了,再重新选举一个的过程。

对于这个问题就是你反客为主的机会 ,因为Kafka中的选举有多处,可不止分区leader的选举这一处,就算指明问分区leader的选举,那么也需要分4种情况具体分析。而这里面的细节是大多数人不甚明了的。

Kafka中的选举大致可以分为三大类:

  • 控制器的选举

  • 分区leader的选举

  • 消费者相关的选举

控制器的选举

在Kafka集群中会有一个或多个broker,其中有一个broker会被选举为控制器(Kafka Controller),它负责管理整个集群中所有分区和副本的状态等工作。

比如当某个分区的leader副本出现故障时,由控制器负责为该分区选举新的leader副本。再比如当检测到某个分区的ISR集合发生变化时,由控制器负责通知所有broker更新其元数据信息。

Kafka Controller的选举是依赖Zookeeper来实现的,在Kafka集群中哪个broker能够成功创建/controller这个临时(EPHEMERAL)节点他就可以成为Kafka Controller。

这里需要说明一下的是Kafka Controller的实现还是相当复杂的,涉及到各个方面的内容,如果你掌握了Kafka Controller,你就掌握了Kafka的“半壁江山”。

分区leader的选举

这里不说什么一致性协议(PacificA)相关的内容,只讲述具体的选举内容。

分区leader副本的 选举由Kafka Controller 负责具体实施。

当创建分区(创建主题或增加分区都有创建分区的动作)或分区上线(比如分区中原先的leader副本下线,此时分区需要选举一个新的leader上线来对外提供服务)的时候都需要执行leader的选举动作。

基本思路是按照AR集合中副本的顺序查找第一个存活的副本,并且这个副本在ISR集合中。

一个分区的AR集合在分配的时候就被指定,并且只要不发生重分配的情况,集合内部副本的顺序是保持不变的,而分区的ISR集合中副本的顺序可能会改变。

注意:这里是根据AR的顺序而不是ISR的顺序进行选举的。这个说起来比较抽象,有兴趣的读者可以手动关闭/开启某个集群中的broker来观察一下具体的变化。

还有一些情况也会发生分区leader的选举,比如当分区进行重分配(reassign)的时候也需要执行leader的选举动作。

这个思路比较简单:从重分配的AR列表中找到第一个存活的副本,且这个副本在目前的ISR列表中。

再比如当发生优先副本(preferred replica partition leader election)的选举时,直接将优先副本设置为leader即可,AR集合中的第一个副本即为优先副本。

还有一种情况就是当某节点被优雅地关闭(也就是执行ControlledShutdown)时,位于这个节点上的leader副本都会下线,所以与此对应的分区需要执行leader的选举。

这里的具体思路为:从AR列表中找到第一个存活的副本,且这个副本在目前的ISR列表中,与此同时还要确保这个副本不处于正在被关闭的节点上。

消费者相关的选举

对于这部分内容的理解,额。。如果你对消费者、消费组、消费者协调器以及组协调器不甚理解的话,那么。。。职能毛遂自荐《深入理解Kafka》一书了,嘿嘿

组协调器GroupCoordinator需要为消费组内的消费者选举出一个消费组的leader,这个选举的算法也很简单,分两种情况分析。

如果消费组内还没有leader,那么第一个加入消费组的消费者即为消费组的leader。

如果某一时刻leader消费者由于某些原因退出了消费组,那么会重新选举一个新的leader,这个重新选举leader的过程又更“随意”了,相关代码如下:

//scala code.
private val members = new mutable.HashMap[String, MemberMetadata]
var leaderId = members.keys.head

解释一下这2行代码:在GroupCoordinator中消费者的信息是以HashMap的形式存储的,其中key为消费者的member_id,而value是消费者相关的元数据信息。

leaderId表示leader消费者的member_id,它的取值为HashMap中的第一个键值对的key,这种选举的方式基本上和随机无异。

总体上来说,消费组的leader选举过程是很随意的。

到这里就结束了吗?还有分区分配策略的选举呢。

或许你对此有点陌生,但是用过Kafka的同学或许对 partition.assignment.strategy(取值为RangeAssignor、RoundRobinAssignor、StickyAssignor等) 这个参数并不陌生。

每个消费者都可以设置自己的分区分配策略,对消费组而言需要从各个消费者呈报上来的各个分配策略中选举一个彼此都“信服”的策略来进行整体上的分区分配。

这个分区分配的选举并非由leader消费者决定,而是根据消费组内的各个消费者投票来决定的。至于具体的细节么。。。嘿嘿。

END

欢迎长按下图关注公众号 石杉的架构笔记 ,后台回复“ 资料 ”,获取作者独家秘制学习资料!

BAT架构经验倾囊相授