持续创作,加速成长!这是我参与「掘金日新计划 · 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
接着把对应全部副本状态变为ReplicaDeletionStarted
Controller
再发送请求这些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
全部改为异步操作。
\