控制器选举流程
- Broker 启动:
- 当 Kafka 集群中的 Broker 启动时,它会尝试成为控制器。
- 每个 Broker 在启动时都会尝试连接到 ZooKeeper,并检查是否存在一个名为
/controller的临时节点。
- 创建临时节点:
- 如果
/controller节点不存在,这意味着目前还没有 Broker 成为控制器。 - 尝试成为控制器的 Broker 将会创建一个临时节点
/controller,并将自己的 Broker ID 写入这个节点。 - 第一个成功创建
/controller节点的 Broker 成为控制器。
- 如果
- 其他 Broker 检测:
- 其他启动的 Broker 也会尝试创建
/controller节点,但在发现该节点已经存在时,它们将读取节点的内容以获取当前控制器的 Broker ID。 - 如果读取到的 Broker ID 不为
-1,表示已经有其他 Broker 成为控制器,这些 Broker 将不再尝试成为控制器。
- 其他启动的 Broker 也会尝试创建
- 控制器失效:
- 如果当前的控制器失效,它将失去与 ZooKeeper 的连接,导致
/controller节点被自动删除。 - 当其他 Broker 检测到
/controller节点消失时,它们会再次尝试创建该节点,从而可能成为新的控制器。
- 如果当前的控制器失效,它将失去与 ZooKeeper 的连接,导致
- 心跳机制:
- 为了防止假死的情况(即控制器仍然活跃但未能及时发送心跳),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 出现故障,控制器的选举也将受到影响。