持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情
一、前言
控制器组件(Controller):是 Apache Kafka 的核心组件
- 主要作用是:在
Apache Zookeeper的帮助下管理和协调整个Kafka集群。 - 集群中任意一台
Broker都能充当控制器的角色,但在运行过程中,只能有一个Broker成为控制器。
问题
2. 创建 Topic 时,Controller 如何实现 Leader 选举?
创建一个 Topic:会分配设置的 partition,以及每个 partition 指定几个副本。
- 这个创建过程就会在
Zk中注册对应的Topic的元数据(partition、副本) - 此时状态都是
NonExistentReplica
白话说 Kafka Controller 本质:
- 监听
Zk上的数据变更 - 感知到
Topic变动,就会从Zk中加载所有partition副本到内存里,并把partition副本状态变更为NewReplica - 然后选择的第一个副本作为
Leader,其他都是follower,并且把他们都放到partition的ISR列表中
举个栗子:创建一个 Topic:order_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]
- 从每个
partition的副本列表中取出第一个作为leader,其他的就是follower,并把这些放到partition对应的ISR列表中 - 把
partition副本均匀分散到各机器上 - 同时设置整个
partition的状态为:OnlinePartition - 接着
Controller会把这个partition和副本所有的信息(哪个是leader、哪个是follower、ISR列表)都发送给所有Broker。
3. 删除 Topic 时,Controller 如何清理数据?
如果要删除某个 Topic,流程如下:
Controller会发送请求给这个Topic所有Partition所在的Broker机器- 通知设置对应所有
Partition副本的状态为:OfflineReplica,即让对应副本全部下线 Controller接着把对应全部副本状态变为ReplicaDeletionStartedController再发送请求这些Broker,让其把对应partition副本的数据都删除(磁盘上的文件),删除成功后,副本状态变更为:ReplicaDeletionSuccessful, 接着再变为NonExistentReplica- 最后设置分区状态为:
OfflineReplica
4. Controller 如何感知 Broker 的上线以及崩溃?
白话说 Kafka Controller 本质:
- 监听
Zk上的数据变更 - 感知到
Broker变更,将信息同步给其他Broker - 分配信息 或 进行
Leader选举
二、原理
控制器的内部设计相当复杂:控制器是多线程的设计,会在内部创建很多线程。如:
- 为每个
Broker创建一个对应的Socket连接,然后在创建一个专属的线程,用于向这些Broker发送特定的请求。 - 控制连接
zookeeper, 也会创建单独的线程来处理Watch机制通知回调。 - 控制器还会为主题删除创建额外的
I/O线程。
这些线程还会访问共享的控制器缓存数据,为了维护数据安全性,控制在代码中大量使用
ReetrantLock同步机制,进一步拖慢了整个控制器的处理速度。
社区于 0.11 版本重构了控制器的底层设计,最大的改进就是:把多线程的方案改成了单线程加事件队列的方案:
这个方案的最大好处在于:控制器缓存中保存的状态只被一个线程处理,因此不再需要重量级的线程同步机制来维护线程安全,Kafka 不用再担心多线程并发访问的问题,非常利于社区定位和诊断控制器的各种问题。
- 将之前同步操作
ZooKeeper全部改为异步操作。
\