控制器选举流程

  1. Broker 启动
    • 当 Kafka 集群中的 Broker 启动时,它会尝试成为控制器。
    • 每个 Broker 在启动时都会尝试连接到 ZooKeeper,并检查是否存在一个名为  /controller  的临时节点。
  2. 创建临时节点
    • 如果  /controller  节点不存在,这意味着目前还没有 Broker 成为控制器。
    • 尝试成为控制器的 Broker 将会创建一个临时节点  /controller,并将自己的 Broker ID 写入这个节点。
    • 第一个成功创建  /controller  节点的 Broker 成为控制器。
  3. 其他 Broker 检测
    • 其他启动的 Broker 也会尝试创建  /controller  节点,但在发现该节点已经存在时,它们将读取节点的内容以获取当前控制器的 Broker ID。
    • 如果读取到的 Broker ID 不为  -1,表示已经有其他 Broker 成为控制器,这些 Broker 将不再尝试成为控制器。
  4. 控制器失效
    • 如果当前的控制器失效,它将失去与 ZooKeeper 的连接,导致  /controller  节点被自动删除。
    • 当其他 Broker 检测到  /controller  节点消失时,它们会再次尝试创建该节点,从而可能成为新的控制器。
  5. 心跳机制
    • 为了防止假死的情况(即控制器仍然活跃但未能及时发送心跳),Broker 会定期向 ZooKeeper 发送心跳。
    • 如果 ZooKeeper 在预定时间内未接收到心跳,它将认为该 Broker 已经失效,并允许其他 Broker 成为新的控制器。

除此之外,Zookeeper 中还有一个与控制器有关的 /controller_epoch 节点,这个节点是持久节点,节点中存放的是一个整型的 controller_epoch 值。controller_epoch 值用于记录控制器发生变更的次数,初始值为 1,每当控制器变更,数值加一。每个和控制器交互的请求都会携带 controller_epoch 这个字段,小于内存的 controller_epoch,请求过期无效;大于内存的 controller_epoch,说明已经有新的控制器当选了,拒绝这个请求。

注意事项

  • 选举的唯一性:由于  /controller  是一个临时节点,一旦创建它的 Broker 失败,该节点将自动被删除,这确保了控制器的唯一性。
  • 选举的公平性:选举过程基于谁先到达的原则,即“先到先得”,因此选举并不一定是按照 Broker ID 的顺序进行的。
  • ZooKeeper 的依赖性:选举过程完全依赖于 ZooKeeper 的正确运行。如果 ZooKeeper 出现故障,控制器的选举也将受到影响。