【Kafka】控制器(二)

138 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情

一、前言

控制器组件(Controller):是 Apache Kafka 的核心组件

  • 主要作用是:在 Apache Zookeeper 的帮助下管理和协调整个 Kafka 集群。
  • 集群中任意一台 Broker 都能充当控制器的角色,但在运行过程中,只能有一个 Broker 成为控制器。

问题

2. 创建 Topic 时,Controller 如何实现 Leader 选举?

创建一个 Topic:会分配设置的 partition,以及每个 partition 指定几个副本。

  • 这个创建过程就会在 Zk 中注册对应的 Topic 的元数据(partition、副本)
  • 此时状态都是 NonExistentReplica

白话说 Kafka Controller 本质:

  1. 监听 Zk 上的数据变更
  2. 感知到 Topic 变动,就会从 Zk 中加载所有 partition 副本到内存里,并把 partition副本状态变更为 NewReplica
  3. 然后选择的第一个副本作为 Leader,其他都是 follower,并且把他们都放到 partitionISR 列表中

举个栗子:创建一个 Topicorder_topic, 有 3个 partition,每个 partition 有2个副本

# 这些元数据都写入到 Zk 中
/topic/order_topic 
​
partition = 3, replica_factor = 2[partition0_1, partition0_2]
[partition1_1, partition1_2]
[partition2_1, partition2_2]
  1. 从每个 partition 的副本列表中取出第一个作为 leader,其他的就是 follower,并把这些放到 partition 对应的 ISR 列表中
  2. partition 副本均匀分散到各机器上
  3. 同时设置整个 partition 的状态为:OnlinePartition
  4. 接着 Controller 会把这个 partition 和副本所有的信息(哪个是 leader、哪个是 followerISR列表)都发送给所有 Broker

3. 删除 Topic 时,Controller 如何清理数据?

如果要删除某个 Topic,流程如下:

  1. Controller 会发送请求给这个 Topic 所有 Partition 所在的 Broker 机器
  2. 通知设置对应所有 Partition 副本的状态为:OfflineReplica,即让对应副本全部下线
  3. Controller 接着把对应全部副本状态变为 ReplicaDeletionStarted
  4. Controller 再发送请求这些 Broker,让其把对应 partition 副本的数据都删除(磁盘上的文件),删除成功后,副本状态变更为:ReplicaDeletionSuccessful, 接着再变为 NonExistentReplica
  5. 最后设置分区状态为:OfflineReplica

4. Controller 如何感知 Broker 的上线以及崩溃?

白话说 Kafka Controller 本质:

  1. 监听 Zk 上的数据变更
  2. 感知到 Broker 变更,将信息同步给其他 Broker
  3. 分配信息 或 进行 Leader 选举

二、原理

控制器的内部设计相当复杂:控制器是多线程的设计,会在内部创建很多线程。如:

  1. 为每个 Broker 创建一个对应的 Socket连接,然后在创建一个专属的线程,用于向这些 Broker 发送特定的请求。
  2. 控制连接 zookeeper, 也会创建单独的线程来处理 Watch 机制通知回调。
  3. 控制器还会为主题删除创建额外的 I/O 线程。

这些线程还会访问共享的控制器缓存数据,为了维护数据安全性,控制在代码中大量使用 ReetrantLock 同步机制,进一步拖慢了整个控制器的处理速度。

社区于 0.11 版本重构了控制器的底层设计,最大的改进就是:把多线程的方案改成了单线程加事件队列的方案:

2022-06-0208-15-54.png

这个方案的最大好处在于:控制器缓存中保存的状态只被一个线程处理,因此不再需要重量级的线程同步机制来维护线程安全,Kafka 不用再担心多线程并发访问的问题,非常利于社区定位和诊断控制器的各种问题。

  • 将之前同步操作 ZooKeeper 全部改为异步操作。

\