Broker 概述
定义与作用
Broker 是 Kafka 集群中的单个服务节点。每个 Broker 运行一个 Kafka Server 进程,负责接收 Producer 的消息写入、服务 Consumer 的消息拉取、维护 Partition 的磁盘存储、管理副本同步。一个 Kafka 集群由 1 到数百个 Broker 组成。
Broker 之于 Kafka,如同 Node 之于分布式系统:无状态的计算节点 + 有状态的存储节点。
核心原理
Broker 的内部架构
| 组件 | 职责 |
|---|---|
| Network Server | 处理 TCP 连接、协议解析 |
| Replica Manager | 管理本节点的所有副本(Leader/Follower) |
| Log Manager | 管理 Partition 的磁盘存储(Segment、清理) |
| Group Coordinator | 负责部分 Consumer Group 的 Rebalance 和 Offset 管理 |
| Transaction Coordinator | 负责部分事务 Producer 的事务状态管理 |
| Metadata Cache | 缓存集群元数据(Topic、Partition、ISR 列表) |
Broker 的生命周期
完整示例
示例一:多 Broker 集群搭建
场景:在单机上模拟 3 个 Broker 组成集群。
操作前环境:Kafka 已安装,当前无 Kafka 进程。
步骤:
cd /opt/kafka
# 1. 准备 3 份配置文件
cp config/kraft/server.properties config/kraft/server1.properties
cp config/kraft/server.properties config/kraft/server2.properties
cp config/kraft/server.properties config/kraft/server3.properties
# 2. 修改 server1.properties
# node.id=1
# listeners=PLAINTEXT://:9092
# log.dirs=/tmp/kraft-logs-1
# controller.quorum.voters=1@localhost:9093,2@localhost:9094,3@localhost:9095
# 3. 修改 server2.properties
# node.id=2
# listeners=PLAINTEXT://:9097
# log.dirs=/tmp/kraft-logs-2
# controller.quorum.voters=1@localhost:9093,2@localhost:9094,3@localhost:9095
# 4. 修改 server3.properties
# node.id=3
# listeners=PLAINTEXT://:9098
# log.dirs=/tmp/kraft-logs-3
# controller.quorum.voters=1@localhost:9093,2@localhost:9094,3@localhost:9095
# 5. 生成集群 ID 并格式化
CLUSTER_ID=$(bin/kafka-storage.sh random-uuid)
bin/kafka-storage.sh format -t $CLUSTER_ID -c config/kraft/server1.properties
bin/kafka-storage.sh format -t $CLUSTER_ID -c config/kraft/server2.properties
bin/kafka-storage.sh format -t $CLUSTER_ID -c config/kraft/server3.properties
# 6. 启动 3 个 Broker
bin/kafka-server-start.sh -daemon config/kraft/server1.properties
bin/kafka-server-start.sh -daemon config/kraft/server2.properties
bin/kafka-server-start.sh -daemon config/kraft/server3.properties
# 7. 验证
jps -l | grep Kafka
# 1234 kafka.Kafka
# 1235 kafka.Kafka
# 1236 kafka.Kafka
操作后状态:
| Broker | node.id | 端口 | 日志目录 |
|---|---|---|---|
| Broker 1 | 1 | 9092 | /tmp/kraft-logs-1 |
| Broker 2 | 2 | 9097 | /tmp/kraft-logs-2 |
| Broker 3 | 3 | 9098 | /tmp/kraft-logs-3 |
示例二:连接任意 Broker 都等价
场景:验证 bootstrap.servers 中任一 Broker 都可以获取完整集群元数据。
# 通过 Broker 1 创建 Topic
bin/kafka-topics.sh --create --topic test --partitions 3 \
--bootstrap-server localhost:9092
# 通过 Broker 2 查看同一 Topic(元数据来自集群)
bin/kafka-topics.sh --describe --topic test \
--bootstrap-server localhost:9097
# 结果相同,因为元数据在集群内共享
# 向 Broker 3 发送消息(会被路由到正确的 Leader)
bin/kafka-console-producer.sh --topic test --bootstrap-server localhost:9098
> hello from broker 3
操作前后对比:
| 连接哪个 Broker | 操作结果 |
|---|---|
| Broker 1:9092 | 创建 Topic → 成功 |
| Broker 2:9097 | 查看 Topic → 看到完整信息(包括 Leader 在各 Broker 上的分布) |
| Broker 3:9098 | 发送消息 → 重定向到正确的 Leader 写入 |
易错场景
易错 1:bootstrap.servers 只填一个地址
场景:bootstrap.servers=kafka1:9092,kafka1 宕机后所有客户端无法连接。
后果:虽然集群还有 kafka2 和 kafka3 在运行,但客户端连接的是 kafka1,无法获取新元数据。
正确做法:bootstrap.servers=kafka1:9092,kafka2:9092,kafka3:9092。客户端会尝试各个地址,连接成功后获取完整 Broker 列表。
易错 2:不同 Broker 使用不同 Cluster ID
现象:格式化存储目录时用了不同 Cluster ID,Broker 启动后日志报错:
ERROR The cluster ID doesn't match
原因:KRaft 模式下所有 Broker 必须属于同一集群,Cluster ID 是集群的唯一标识。
解决:确保所有 Broker 用同一个 Cluster ID 格式化。
面试高频考点
Q:为什么连接 Kafka 集群的任意一个 Broker 就可以访问整个集群?
A:Kafka 客户端采用"懒发现"机制:
- 连接
bootstrap.servers中的任意地址 - 发送 Metadata Request 获取完整集群元数据(所有 Broker 地址、Topic 分区信息)
- 缓存元数据,后续请求直接发往目标 Broker(如 Partition Leader 所在的 Broker)
- 元数据定期刷新(
metadata.max.age.ms,默认 5 分钟)或遇到错误强制刷新
这意味着 Broker 之间是对等的——不像 NameNode/DataNode 有主从之分。