- 控制器组件(Controller),是 Apache Kafka 的核心组件。它的主要作用是在 Apache ZooKeeper 的帮助下管理和协调整个 Kafka 集群
- 集群中任意一台 Broker 都能充当控制器的角色,但是,在运行过程中,只能有一个 Broker 成为控制器,行使其管理和协调的职责
- 有个
activeController
的 JMX 指标,可以帮助我们实时监控控制器的存活状态- 如果值大于 1,表示集群出现脑裂
如何选举控制器
- 控制器是重度依赖 ZooKeeper
- Kafka 控制器大量使用 Watch 功能实现对集群的协调管理
- Broker 在启动时,会尝试去 ZooKeeper 中创建 /controller 节点
- Kafka 当前选举控制器的规则是:第一个成功创建 /controller 节点的 Broker 会被指定为控制器
控制器职责
主题管理(创建、删除、增加分区)
- 当我们执行
kafka-topics
脚本时,大部分的后台工作都是控制器来完成的
分区重分配
分区重分配主要是指,
kafka-reassign-partitions
脚本提供的对已有主题分区进行细粒度的分配功能Preferred 领导者选举主要是 Kafka 为了避免部分 Broker 负载过重而提供的一种换 Leader 的方案
集群成员管理(新增 Broker、Broker 主动关闭、Broker 宕机)
- 包括自动检测新增 Broker、Broker 主动关闭及被动宕机
- 这种自动检测是依赖于前面提到的 Watch 功能和 ZooKeeper 临时节点组合实现的。
- 每个 Broker 启动后,会在
/brokers/ids
下创建一个临时 znode。当 Broker 宕机或主动关闭后,该 Broker 与 ZooKeeper 的会话结束,这个 znode 会被自动删除 - 控制器组件会利用 Watch 机制检查 ZooKeeper 的
/brokers/ids
节点下的子节点数量变更
- 每个 Broker 启动后,会在
数据服务
- 控制器上保存了最全的集群元数据信息,其他所有 Broker 会定期接收控制器发来的元数据更新请求,从而更新其内存中的缓存数据
控制器保存的数据
- 这些数据其实在 ZooKeeper 中也保存了一份
- 每当控制器初始化时,它都会从 ZooKeeper 上读取对应的元数据并填充到自己的缓存中
比较重要的数据
- 所有主题信息
- 包括具体的分区信息,比如领导者副本是谁,ISR 集合中有哪些副本等。
- 所有 Broker 信息
- 包括当前都有哪些运行中的 Broker,哪些正在关闭中的 Broker 等。
- 所有涉及运维任务的分区
- 包括当前正在进行 Preferred 领导者选举以及分区重分配的分区列表。
控制器故障转移(Failover)
- 由于控制器只有一个,可能出现 单点失效
- Failover,即故障转移指的是,当运行中的控制器突然宕机或意外终止时,Kafka 能够快速地感知到,并立即启用备用控制器来代替之前失败的控制器
- 当控制器宕机后,ZooKeeper 通过 Watch 机制感知到并删除了 /controller 临时节点
- 所有存活的 Broker 开始竞选新的控制器身份
- 存活的 Broker 开始竞选新的控制器身份,第一个成功地在 ZooKeeper 上重建了 /controller 节点的 Broker 会争夺到控制器
控制器设计
改进1
- 0.11 版本重构了控制器的底层设计,最大的改进就是把多线程的方案改成了单线程加事件队列的方案
- 社区引入了一个事件处理线程,统一处理各种控制器事件,然后控制器将原来执行的操作全部建模成一个个独立的事件,发送到专属的事件队列中,供此线程消费
- 把缓存状态变更方面的工作委托给了这个线程
- 这就是所谓的单线程 + 队列的实现方式
- 社区引入了一个事件处理线程,统一处理各种控制器事件,然后控制器将原来执行的操作全部建模成一个个独立的事件,发送到专属的事件队列中,供此线程消费
改进2
- 将之前同步操作 ZooKeeper 全部改为异步操作
- 当有大量主题分区发生变更时,ZooKeeper 容易成为系统的瓶颈
改进3
- 不过自 2.2 开始,Kafka 正式支持这种不同优先级请求的处理
- Kafka 将控制器发送的请求与普通数据类请求分开,实现了控制器请求单独处理的逻辑
手动删除 /controller
节点
- 控制器组件出现问题时,比如主题无法删除了,或者重分区 hang 住了,不用重启 Kafka Broker 或控制器
- 有一个简单快速的方式是,去 ZooKeeper 中手动删除
/controller
节点。具体命令是rmr /controller
- 这样做的好处是,既可以引发控制器的重选举,又可以避免重启 Broker 导致的消息处理中断。