Kafka-控制器

控制器其实就是一个broker,只不过它除了具有一般broker的功能之外,还负责分区首领的选举。集群里第一个启动broker通过在zookeeper里创建一个临时节点/controller让自己成为控制器。其他broker在启动时也会尝试创建这个节点,不过它们会收到一个节点已存在的异常,然后意识到控制器节点已存在,也就是说集群里已经有一个控制器了。其他broker在控制器节点上创建zookeeper watch对象,这样它们就可以收到这个节点的变更通知。这种方式可以确保集群里一次只有一个控制器存在。

如果控制器被关闭或者与zookeeper断开连接,zookeeper上的临时节点就会消失。集群里的其它broker通过watch对象得到控制器节点消失的通知,他们就会尝试让自己成为新的控制器。第一个在zookeeper里成功创建控制器节点的broker就会成为新的控制器,其它节点会收到节点已存在的异常,然后在新的控制器节点上再次创建watch对象。每个新选出的控制器通过zookeeper的条件递增操作获得一个全新的、数值更大的controller epoch。其它broker在知道当前controller epoch后,如果收到由控制器发出的包含较旧epoch的消息,就会忽略它们。

当控制器发现一个broker已经离开集群(通过观察相关的zookeeper路径),它就知道,那些失去首领的分区需要一个新首领(这些分区的首领刚好是在这个broker上)。控制器遍历这些分区,并确定谁应该成为新首领(分区副本列表里的下一个副本),然后向所有包含新首领或现有跟随者的broker发送请求。该请求消息包含了谁是新首领一级谁是分区跟随者的信息。随后,新首领开始处理来自生产者和消费者的请求,而跟随者开始从新首领那里复制消息。

当控制器发现一个broker加入集群时,它会使用brokerID来检查新加入的broker是否包含现有分区的副本。如果有,控制器就把变更通知发送给新加入的broker和其他broker,新broker上的副本开始从首领那里复制消息。

kafka使用zookeeper的临时节点来选举控制器,并在节点加入集群或退出集群时通知控制器。控制器负责在节点加入或离开集群时进行分区首领选举,控制器使用epoch来避免“脑裂”。“脑裂”是指两个节点同时认为自己是当前的控制器。