kafka--基础知识点--8--Controller选举/leader选举

1 Controller 选举

kafka控制器管理着整个集群中分区以及副本的状态,控制器的选举需要依赖于Zookeeper,在kafka集群启动的时候,会在ZK中创建一个临时节点(EPHEMERAL)/controller,在每个Broker启动的时候,都会先去访问ZK中的这个节点,如果不存在Broker就会则创建这个节点,先到先得称为Controller,其它Broker当访问这个节点的时候,如果读取到brokerid不等于-1,那么说明Controller已经被选举出来了,这个/controller下面的信息为:

[zk: localhost:2181(CONNECTED) 3] get /controller 
{"version":1,"brokerid":0,"timestamp":"1608173427409"}

#其中version为固定的版本号1
#brokerid为控制器的broker节点id
#timestamp为改节点被选举成Controller的时间

在任何时候,集群中只能存在1个控制器,ZK中还维护着Controller的一个永久节点(PERSISTENT)/controller_epoch,该节点记录着控制器的变更次数,这个节点的初始值=1,每选举一次Controller那么该值+1。

身为Controller的Broker比其它的Broker多一些职责,具体为下

  • 监听分区相关的变化
    • 为ZK中的/admin/reassign_partitions节点注册PartitionReassignmentHandler用来处理分区重新分配的动作
    • 为ZK中的/admin/isr_change_notification节点注册IsrChangeNotificetionHandler ,用来处理ISR副本集合的变更动作
    • 为ZK中的admin/preferred-replica-election节点添加PreferredReplicaElectionHandler,用来处理优先副本选举的动作
  • 监听主题相关的变化
    • 为ZK中的/brokers/topics节点添加TopicChangeHandler,用来处理主题增减的变化
    • 为ZK中的/admin/delete_topics节点注册TopicDeletionHandler,用来处理主题的删除动作
  • 监听Broker的变化
    • 为ZK中的/brokers/ids节点添加BrokerChangeHandler,用来处理Broker增减的变化
  • 从ZK中获取Broker、Topic、Partition相关的元数据信息
    • 为/brokers/topics/节点注册PartitionModificationHandler,主题中分区分配的变化
  • 启动并管理分区状态机和副本状态机
  • 更新集群的元数据信息,并同步给其它的Broker
  • 如果开启了自动优先副本选举,那么会后台启动一个任务用来自动维护优先副本的均衡。

具体的控制器职责相关的ZK监听节点的创建与监听器的注册图如下:
在这里插入图片描述
在控制器被选举之后,会在ZK中的每个节点下读取对应的元数据信息,创建集群的上下文信息:ControllerContext,并且管理上下文信息,假如有broker节点变更、分区变更、leader变更,都会将变更信息更新到上下文中,同时会将变更过后的上下文信息同步到其它的Broker中,这样就会设计多线程间同步,如果单纯的使用锁机制,那么性能会大打折扣,kafka使用单线程基于事件队列的模型,将每个变更的事件event进行封装,然后放入到LinkedBlockingQueue中,最后使用一个专用的线程ControllerEventThread按照FIFO的原则顺序的处理每个事件,这样利用单线程的模式避免了多线程的线程安全问题。

NOTE:在早期的版本中,并没有采用KafkaController的形式对分区和副本状态进行管理,而是依赖于Zookeeper,每个Broker都会在ZK中注册大量的监听器,并在ZK中创建对应的监听节点,在分区和副本变化的时候,会启动很多不必要启动的监听器,这种依赖于ZK的方式会有造成Kafka脑裂,严重的时候还会造成ZK节点过多而过载的情况,目前版本只有KafkaController才会在ZK上注册监听器,其它的Broker极少需要监听ZK,不过broker还是会对临时的Controller节点进行监听,每个broker都会自身维护activeControllerId(在线的controllerid),如果Broker在数据变更前是Broker,变更后的activeControllerId与自己的Brokerid不一样,那么就会“退位”,这时候就会启动重新选举。如果有需要,可以手动删除/controller节点,触发重新选举

2 分区副本-leader的选举

kafka中的分区的leader的选举操作也是通过controller完成的,副本的选举一般是在创建topic的时候和leader上下线的时候。

  • 从Zookeeper中读取当前分区的所有ISR(in-sync replicas)集合
  • 调用配置的分区选择算法选择分区的leader

如何处理所有Replica都不工作?

在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的数据源(前文有说明,所有读写都由Leader完成)。Kafka0.8.*使用了第二种方式。根据Kafka的文档,在以后的版本中,Kafka支持用户通过配置选择这两种方式中的一种,从而根据不同的使用场景选择高可用性还是强一致性。 unclean.leader.election.enable 参数决定使用哪种方案,默认是true,采用第二种方案

在这里插入图片描述
controller会在Zookeeper的/brokers/ids节点上注册Watch,一旦有broker宕机,它就能知道。当broker宕机后,controller就会给受到影响的partition选出新leader。controller从zk的/brokers/topics/[topic]/partitions/[partition]/state中,读取对应partition的ISR(in-sync replica已同步的副本)列表,选一个出来做leader。

选出leader后,更新zk,然后发送LeaderAndISRRequest给受影响的broker,让它们改变知道这事。为什么这里不是使用zk通知,而是直接给broker发送rpc请求,我的理解可能是这样做zk有性能问题吧。

如果ISR列表是空,那么会根据配置,随便选一个replica做leader,或者干脆这个partition就是歇菜。如果ISR列表的有机器,但是也歇菜了,那么还可以等ISR的机器活过来。

注意:

  • zookeeper中的leader/follower、kafka中的controller、kafka中的leader/follower的区别,这是几个不同的概念。zookeeper中的leader/follower与kafka中的controller、kafka中的leader/follower没有任何关系。kafka中的leader/follwer是通过kafka中的controler产生的

Kafka-之控制器(Controller选举、leader选举)
kafka集群 leader选举机制(浅显易懂)

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值