在任意时刻,Kafka 集群中有且仅有一个控制器 。每个 broker 启动时会尝试读取 ZooKeeper 的 /controller 节点的 brokerid 的值,如果 brokerid ≠ -1 , 则表示当前集群已有控制器,broker 就会放弃竞?。蝗绻?淮嬖?/controller 节点,broker 就会尝试创建节点,创建成功的 broker 就会成为控制器,将自己的 ID 赋予 brokerid,而对于创建节点失败的 broker 则会在内存中保存当前控制器的 brokerid 值,这个值标识为 activeControllerId 。
上面是启动 Kafka 集群以及正常情况下添加 broker 情况下的选举过程 。那么当控制器出现故障时,就需要重新选举了 。ZooKeeper 中还有一个与控制器有关的 /controller_epoch 节点,该节点是持久节点,里面存储了一个整型的 controller_epoch 值,初始值是 1 。当控制器发生变化时,controller_epoch 就会加 1 。每个和控制器交互的请求一定会带上 controller_epoch , 当控制器发现请求带上的 controller_epoch 比自己内存的小,那么这个请求则是无效请求;如果请求带上的 controller_epoch 比自己内存的大,说明自己不再是控制器 。由此可见,Kafka 是通过 controller_epoch 来保证控制器的唯一性,进而保证相关操作的一致性 。
这里再扩展一下,说下作为控制器的 broker 多出来的责任:
- 监听分区相关的变化
– 在 ZooKeeper 的 /isr_change_notification 节点注册 IsrChangeNotificetionHandler,用来处理 ISR 集合变更的动作 。
– 在 ZooKeeper 的 /admin/preferred-replica-election 节点注册 PreferredReplicaElectionHandler,用来处理优先副本的选举动作 。
- 监听主题相关的变化
– 在 ZooKeeper 的 /admin/delete_topics 节点注册 TopicDeletionHandler,用来处理删除主题的动作 。
- 监听 broker 相关的变化
- 从 ZooKeeper 中读取当前所有与主题、分区及 broker 有关的信息并进行相应的管理
- 启动并管理分区状态机和副本状态机
- 更新集群的元数据信息
- 如果设置了 auto.leader.rebalance.enable = true , 则还会开启一个名为“auto-leader-rebalance-task”的定时任务来负责维护分区的优先副本的均衡
控制器、非控制器 broker、ZooKeeper 的关系图如下:
文章插图
文章插图
只有控制器会注册相应的监听器关注节点的数据变化,其他 broker 则不关注这些节点的数据变化(除了 /controller) 。因为所有 broker 都会关心当前的控制器到底是谁,当 /controller 的数据发生变化时 , 就要更新自己内存中的 activeControllerId 。如果原来是控制器的 broker,发现自己现在不是了,就需要关闭资源 , 如注销只有控制器才需要的监听器等 。不管什么原因造成 /controller 的 brokerid 变更,再重新选举控制器之前,要先确定参选的 broker 里面是否有前控制器,如果有,就要先“退位”,再开始新的选举 。
优点:只有控制器注册监听器 , 可以有效避免严重依赖 ZooKeeper 的设计的通病——脑裂、羊群效应、ZooKeeper 过载 。5 日志同步机制在多副本的设计中,要实现数据一致性和顺序性 , 最简单有效的办法就是选举 leader,由 leader 负责写入顺序,follower 复制同步即可 。只要 leader 不出问题,如宕机、脑裂等,那么就不需要担心 follower 的数据同步问题 。
推荐阅读
- 大型语言模型 一文带你解密 Large Language Model
- 为什么 Kafka 的吞吐量那么高?
- 一文带你了解Spring Actuator
- 一文带你彻底了解JMX
- K8s部署方式大全:从基础到进阶,一文带你掌握所有技巧
- 秦昊带你爬山是什么梗
- 如何确定Apache Kafka的大小和规模
- 什么是抗初老精华,真正有用值得入手有哪些?这6款精华带你了解
- 《小巷人家》开机,关晓彤、周洁琼、卢昱晓带你感受时代里的故事
- 带你了解衸笥愕乃茄?椒ǎù?懔私庑■笥愕乃茄?椒ㄊ鞘裁矗?