集群架构解剖:Broker、Topic、Partition、Replica、Controller、ZooKeeper 的角色与协作机制
很多人学 Kafka,上来就配参数、调吞吐量,结果集群一出问题就抓瞎。为什么?因为没搞懂这几个核心角色到底在干什么。
今天我就带你把这些角色拆开来看。Broker、Topic、Partition、Replica、Controller、ZooKeeper——它们各自管什么,怎么配合,踩过哪些坑。这部分搞透了,后面调优你才有底气。
1. Broker:集群里的每一台机器
Broker 说白了就是一台 Kafka 服务器进程。你部署一个 Kafka 实例,就启动了一个 Broker。多个 Broker 组成集群。
每个 Broker 有一个唯一 ID(broker.id),启动时注册到 ZooKeeper。客户端生产或消费数据,本质上就是跟 Broker 打交道。
核心职责:
- 接收生产者发来的消息,写入磁盘
- 响应消费者的拉取请求
- 管理分区副本的同步
- 参与 Controller 选举
我在项目中遇到过一个问题:某台 Broker 磁盘写满了,整个分区不可用。后来才意识到,Broker 的磁盘容量规划不能只看总量,要看每个 Broker 上的分区分布是否均匀。
2. Topic 与 Partition:逻辑与物理的分层
Topic 是逻辑概念,你往 Kafka 写数据,先得指定一个 Topic。但真正存数据的是 Partition。
一个 Topic 可以拆成多个 Partition,每个 Partition 是一个有序的、不可变的日志文件。Partition 内部的消息按 offset 编号,追加写入。
我的习惯:Topic 的分区数一般设为 Broker 数的 2-3 倍。太少会导致并发瓶颈,太多会增加管理开销。具体多少,得结合你的生产消费速率来压测。
为什么要分区?说白了就是为了并行。一个 Partition 只能被一个消费者实例消费,分区多了,消费者就能并行拉取,吞吐量就上去了。
| 概念 | 层级 | 特点 |
|---|---|---|
| Topic | 逻辑 | 面向业务,一个 Topic 对应一类消息 |
| Partition | 物理 | 实际存储单元,有序、可并行 |
3. Replica:副本机制与数据安全
Kafka 的高可用靠的就是副本。每个 Partition 可以有多个副本,分布在不同的 Broker 上。
副本分两种角色:
- Leader:负责处理读写请求。生产者和消费者只跟 Leader 交互。
- Follower:只做一件事——从 Leader 拉取数据,保持同步。
Leader 挂了怎么办?Controller 会从 ISR(In-Sync Replica)列表里选一个新的 Leader。ISR 是那些跟 Leader 保持同步的副本集合。
我曾经踩过的坑:副本数设成了 3,但 Broker 只有 2 台。结果 Leader 挂了之后,ISR 里没有可用副本,整个分区不可用。副本数不能超过 Broker 数,这是铁律。
4. Controller:集群的“大脑”
Controller 是集群里最特殊的 Broker。它负责管理整个集群的元数据和状态变更。
Controller 的职责包括:
- 处理 Broker 上下线
- 分配分区 Leader
- 管理分区副本的重新分配
- 监听 ZooKeeper 的变更通知
Controller 是通过 ZooKeeper 选举出来的。所有 Broker 启动时都会尝试在 ZooKeeper 上创建临时节点 /controller,谁创建成功,谁就是 Controller。
你想想看,如果 Controller 挂了怎么办?ZooKeeper 的临时节点会消失,其他 Broker 收到通知,重新发起选举。整个过程几秒钟内完成。
注意:Controller 是单点的。虽然选举很快,但如果 Controller 本身负载过高,会影响整个集群的元数据操作。我建议监控 Controller 的 CPU 和网络 IO,别让它成为瓶颈。
5. ZooKeeper:集群的“注册中心”
ZooKeeper 在 Kafka 里扮演的角色,说白了就是存元数据和做协调。
它主要存这些东西:
- Broker 列表(/brokers/ids)
- Topic 与 Partition 的元数据(/brokers/topics)
- Controller 信息(/controller)
- 消费者组的 offset(旧版本,新版本已移到 Kafka 内部 Topic)
ZooKeeper 的节点是临时节点,Broker 挂了,节点自动消失,Controller 就能感知到。
我的建议:ZooKeeper 集群一定要独立部署,别跟 Kafka Broker 混在一起。ZooKeeper 对 IO 敏感,混部容易互相影响。另外,ZooKeeper 的版本要跟 Kafka 版本匹配,不匹配会导致各种奇怪问题。
6. 协作机制:一次消息写入的完整路径
光讲概念不够,我们走一遍流程。假设生产者要往 Topic-A 写一条消息:
- 生产者向集群请求 Topic-A 的元数据,拿到每个 Partition 的 Leader 所在的 Broker。
- 生产者根据分区策略(比如 key 哈希),决定写入哪个 Partition。
- 生产者直接向该 Partition 的 Leader Broker 发送消息。
- Leader 将消息写入本地日志,同时 Follower 从 Leader 拉取数据。
- 当 ISR 中所有副本都确认写入后,Leader 向生产者返回 ack。
- 如果 Leader 挂了,Controller 从 ISR 中选出新 Leader,生产者自动重试。
整个过程,ZooKeeper 只负责存元数据和通知变更,不参与数据路径。这也是 Kafka 高性能的原因之一——数据不走 ZooKeeper。
核心原则:ZooKeeper 管“谁是谁”,Broker 管“数据在哪”,Controller 管“谁来干”。各司其职,互不干扰。
7. 架构全景图
下面这张图把整个协作关系画出来了。你看一眼,应该就能记住。
8. 避坑总结
最后,我把这些年踩过的坑和总结的经验列出来,你直接拿去用:
- 副本数不要超过 Broker 数。否则 Leader 挂了,ISR 里没副本可用。
- 分区数不是越多越好。太多分区会导致文件句柄暴增、Leader 选举变慢。一般单 Broker 分区数不超过 2000。
- ZooKeeper 必须独立部署。混部会导致 ZooKeeper 响应变慢,进而影响 Controller 的选举和元数据操作。
- Controller 要监控。如果 Controller 的 CPU 飙高,检查是不是有频繁的 Broker 上下线或分区重分配。
- ISR 大小要关注。如果 ISR 经常小于副本数,说明 Follower 跟不上 Leader,可能是网络或磁盘 IO 问题。
嗯,这部分内容就到这里。你把这些角色和协作机制理清楚了,后面调优的时候,你才知道改哪个参数会影响谁,不会瞎调。