? 作者:谢先生。 2014年入行的程序猿。多年开发和架构经验。专注于Java、云原生、大数据等技术。从CRUD入行,负责过亿级流量架构的设计和落地,解决了千万级数据治理问题。
? 微信公众号、B站:搜索「谢先生说技术」不定时更新 ~
? 清单: goku-framework、【定期开源】享阅读II
前言
通过之前几章的介绍,我们对Producer有了一定的认识。接下来我们将开启新篇章:Broker
本次我们将从如下方面对Broker进行介绍
- Broker工作原理与ZK
- Broker节点管理
- Broker副本选举、故障处理、放置策略等
- Broker数据存储、清除策略等
Broker预计4~5章结束~
Broker
入门Broker
我们先来对Broker有一个清晰的认识:
Broker是指Kafka集群中的一个节点,负责处理客户端请求、同时也处理客户端发送数据的存储与复制。Kafka集群由多个Broker节点组成,并且每个Broker都有全局唯一的id标识~
可以说: Broker是整个Kafka集群的基本单元,也是整个集群的核心组件。
QA:与物理器节点的关系
这里需要特别与服务器节点区别:
- 服务器节点是指Kafka集群中的物理与虚拟机器,可以是物理服务器、ECS等机器。 同时Broker可以运行在单独的物理机器上,也可以当多个Broker执行在同一台物理机器。
因此,Broker与物理器节点可以是一对一,也可以是多对一的关系
Broker入门原理
Controller
一般集群模式分为主从模式、主备模式等。但是在kafka集群中各broker间不存在主从、主备的关系。
但是为了能够更好的管理broker上下线、topic分区等工作,broker间会选取出Controller的角色,由当前角色做管理工作。 整个集群中只会出现一个Controller角色。
Controller一般是与Zookeeper协助管理整个Kafka集群
选举过程
既然Controller是由broker间的选举,那么它们的选举流程是什么呢? 其实非常简单:
- 在每个broker启动时,都会与zookeeper进行交互,而第一个创建成功
/controller
的broker节点即被选举为Controller
Controller职责
当某个broker成功当选Controller之后,那么他将为整个Kafka集群服务,包括但不限定于:
- 集群内Broker节点管理: 包括新增、下线等
- 副本Leader选举、分区重分配
总之,所有与Zookeeper相交互的工作,都是Controller角色来完成
– 集群内Broker节点管理
所有Broker在启动之后都会向/brokers/ids
下注册一个临时节点,Controller所在Broker节点通过watch
功能监听节点变化,一旦/brokers/ids
下的节点信息发生创建、删除、数据变化等,Controller就能通过监听回调的方式尽快对节点变化做出响应。 例如:
- 当集群中Broker下线
当某个Broker由于某种原因下线,/brokers/ids
下对应信息发生删除,进而通知到Controller节点。
下线之后,存在与该Broker上的Leader分区将不再可用,此时为了最大程度减少集群对外响应时间,Controller将快速找到替代的Leader分区。保证集群的正常可用~
– Leader选举、分区重分配
将Topic分区副本均匀的分布在集群的不同Broker上,最大程度的保证了集群的负载均衡。而当Broker节点发生变化,例如某个Broker下线,那么其它Broker上的分区副本会被选举为Leader。
Controller在选举Leader过程中,都是基于ISR列表来选择,如果副本不存在与ISR中,它是没有选举资格的~
为了最大程度的保证集群的负载均衡能力,kafka会定期对一些分区进行Leader重新选举。而在此过程中有可能会出现原先Follower升级为Leader分区,此时客户端通信、副本交互等请求都会做相应的调整。
auto.leader.rebalance.enabled=true,建议生产环境设置为false
那至于更多更详细的部分,后面在介绍broker节点与副本管理的时候还会细致说明~
Controller故障与脑裂
当Controller所属broker节点发生故障下线,而在Kafka集群中必须存在一个Controller进行集群管理,那么:
- 由于旧Controller与Zookeeper间链接中断,造成会话失效,从而导致注册的
/controller
节点被删除。 - 基于Zookeeper事件监听机制,其余的Broker节点发现这一现象并且开始争抢注册,例如
Broker2
成功在Zookeeper中创建,此时Broker2就是会成为新的Controller角色
— 这是一条分割线
集群属于分布式环境,进而有多种因素会造成Broker与Zookeeper间的会话失效,例如:
- 网络波动造成Controller与Zookeeper连接会话失效
- 长时间GC无响应导致与Zookeeper连接会话失效
- …
而如上原因也必将导致旧Controller无法接收到新Controller选举结果,那么当网络或者GC恢复之后,由于缺少了部分记忆,旧Controller还以为自己是Controller角色,在集群中就出现两个Controller角色,发出具有冲突性的命令。从而导致脑裂现象出现。
脑裂现象在分布式场景下非常常见,参考CAP定理
而脑裂问题不解决,会导致严重数据不一致现象。故而在Kafka中引入了epoch number
来解决这个问题
epoch number
仅仅是一个单调递增的数字,每次Controller角色的选举都会加1,同时Zookeeper回调会将当前epoch number
通知到其它broker节点- 如果在Controller发布的命令中,包含了比当前
epoch number
更小的值,那么broker会忽略这条命令,不做任何操作
Zookeeper因为故障选举Leader也有类似的机制
Broker工作原理
接下来回到正题,关于Broker工作流程其实我们已经介绍过一部分了,接下来我们来看:
- kafka集群间的Broker节点在启动后会向ZK注册启动信息,具体注册在
/brokers/ids
下 - 同时还会去
/controller
下注册,那个Broker节点注册成功,就会成为Controller,并且Controller会监听/broker/ids
下broker的节点变化信息,用来节点管理、分区等 - Topic属于逻辑概念,Topic下的Partition属于物理概念真实存在。Partition属于主从结构,Controller会根据ISR中存活为前提,按照AR排序优先原则选举出Partition的Leader分区
- 如果Controller检测到Broker的Leader挂掉,那么Controller将会从ZK中获取ISR列表并且开始选举新的Leader,ZK在topic下更新leader以及isr列表
- 而如果Controller发生故障,
/controller
会话失效,其它Broker节点谁能在/controller
下注册成功,即为Controller,并且epoch number
递增 - 而新的Controller从ZK中同步到相关数据,从而能够维持集群的正常运行
ZK存储信息
而关于Kafka与ZK交互存储了多少信息,我们一点点来看:
本人用一张图来列出其中关键的部分,如图
-
/brokers/ids
下记录了整个集群中有多少broker节点,对应的[0,1,2]即为broker配置中的broker.id信息,内容如下所示 -
/brokers/topics/{topic}/partitions/[0,1,2]/state
下记录了相关Topic中各分区的相关信息,包括Leader、ISR列表,如下所示
{
"controller_epoch" : 5,
"leader": 2,
"version" : 1,
"leader_epoch": 3,
"isr”: [ 2, 0]
}
/controller
记录的哪位broker节点当选Controller角色,当选时间等
{"version":1,"brokerid":2, "timestamp":"1686192331713"}
其它更多内容大家可以自行查看
Kafka在2.8.0之后推出了Kraft模式,Kafka-Kraft模式部署能够省略ZK的维护
最后
到这里,多说一点:
- Broker部分更多是理论内容,代码部分偏少
本章作为Broker的入门介绍,到这里就全部结束,接下来介绍Broker负载均衡等相关内容
期待~