2. Kafka核心概念与架构

理解Kafka的架构,关键不是背下八个名词,而是搞清楚一条消息从产生到被消费,中间经过了哪些角色、每个角色承担什么职责、它们之间如何协作。本章围绕Topic、Partition、Replica、Broker、Producer、Consumer、Controller、ZooKeeper/KRaft这条主线,把静态概念还原成动态流程。

一、Topic与Partition:逻辑分类与物理并行

Topic是消息的逻辑分类,比如order-events、user-behavior。Producer发消息时指定Topic,Consumer订阅Topic。但Topic本身不存储数据,真正存储和并行的是Partition。

一个Topic可以划分为多个Partition,每个Partition是一个有序、不可变的消息序列,消息以追加方式写入,每条消息获得一个单调递增的offset。Partition是Kafka并行度的基本单位:同一Consumer Group内,一个Partition同一时刻只能被一个Consumer实例消费;因此Partition数决定了该Group的最大并行消费能力。

假设创建Topic时指定3个Partition,消息按key哈希或轮询分配到不同Partition。若key为订单ID,相同订单的消息进入同一Partition,从而保证该订单内消息有序;若key为null,则轮询分配,全局有序性不再保证。这是实际设计时必须明确的取舍。

bin/kafka-topics.sh --create \
  --topic order-events \
  --partitions 3 \
  --replication-factor 2 \
  --bootstrap-server localhost:9092

执行后可用--describe查看分区分布:每个Partition有一个Leader和若干Follower,分布在不同的Broker上。这里已经引出下一个概念:Replica。

二、Replica:数据高可用的复制机制

Replica是Partition的副本。每个Partition有一个Leader副本和零个或多个Follower副本。Producer和Consumer只与Leader交互读写,Follower主动向Leader拉取消息保持同步。

副本集合中有一个ISR(In-Sync Replicas)列表,表示与Leader保持同步的副本。判断“保持同步”的依据是Follower的LEO(Log End Offset)与Leader的LEO差距未超过replica.lag.time.max.ms(默认30秒)。当Leader宕机,Controller会从ISR中选出一个新Leader,从而保证数据不丢失(在acks=all且min.insync.replicas满足时)。

举例:3副本、min.insync.replicas=2、Producer设置acks=all。此时消息必须写入Leader并同步到至少1个Follower才返回成功。若可用ISR只剩1个,写入会被拒绝,这是用可用性换一致性的典型配置。面试中常问“acks取值与可靠性关系”,答案就落在这里。

三、Broker与Controller:集群的存储与协调

Broker是Kafka服务实例,负责接收Producer写入、响应Consumer读取、存储Partition数据。多个Broker组成集群,每个Broker有唯一broker.id。Partition的Leader分散在不同Broker上,实现负载均衡。

Controller是集群中一个特殊的Broker角色,由选举产生。它负责Partition Leader选举、副本分配、Broker上下线处理等集群级管理。Controller不直接参与消息读写,而是维护集群元数据的一致性。当某个Broker宕机,Controller感知后为受影响Partition重新选主,并把新状态同步给其他Broker。

四、Producer与Consumer:写入与读取的两端

Producer发送消息时,先经过序列化器、分区器,确定目标Partition,再批量发送到该Partition的Leader。关键参数包括:acks(0/1/all)、retries、batch.size、linger.ms。批量越大、等待越久,吞吐越高但延迟越大,需要按业务权衡。

Consumer以Consumer Group为单位消费。Group内每个Partition分配给一个Consumer,分配由Group Coordinator协调。Consumer通过fetch.min.bytes、max.poll.records等参数控制拉取行为。offset提交方式分自动与手动,手动提交能更精确控制重复消费范围。

一个常见面试点:Consumer数量超过Partition数时,多出的Consumer会空闲。因此扩容Consumer前应先评估Partition数是否足够。

五、ZooKeeper与KRaft:元数据管理的演进

早期Kafka依赖ZooKeeper存储元数据:Broker注册、Topic配置、Controller选举、ACL等。ZooKeeper是独立集群,运维成本高,且Controller故障恢复依赖ZooKeeper,规模大时成为瓶颈。

KRaft模式用Kafka自身实现元数据管理,引入Controller Quorum(一组Controller节点),元数据以日志形式在Controller间复制。KRaft去掉了ZooKeeper依赖,支持更大规模集群和更快故障恢复。Kafka 3.3起KRaft可用于生产,新项目建议直接采用KRaft。

六、角色关系串联:一条消息的完整旅程

把上述角色串起来:Producer根据key选定Partition,向该Partition的Leader Broker发送消息;Leader写入本地日志,Follower拉取同步,ISR维护同步状态;消息持久化后,Consumer Group中的某个Consumer从Leader拉取消息,按offset消费并提交位。若Leader所在Broker宕机,Controller从ISR选出新Leader,Producer和Consumer通过元数据刷新感知新Leader并继续工作。整个过程由ZooKeeper或KRaft维护元数据一致性。

七、面试速查表

概念核心职责关键点
Topic消息逻辑分类不存储数据,由Partition承载
Partition存储与并行单位有序、offset递增、决定并行度
Replica数据高可用Leader/Follower、ISR、选主
Broker服务实例存储Partition、读写请求
Controller集群管理选主、副本分配、故障处理
Producer写入端分区、批量、acks
Consumer读取端Group、offset、再均衡
ZooKeeper/KRaft元数据管理KRaft为演进方向