Kafka + KRaft 模式架构基础介绍
·
Kafka + KRaft 模式架构基础介绍
适用版本:Kafka 3.3+(生产推荐)
一、概述:为什么使用 KRaft?
自 Kafka 2.8 起,社区引入 KRaft(Kafka Raft Metadata)模式,旨在完全移除对 ZooKeeper 的依赖。从 Kafka 3.3 开始,KRaft 成为官方推荐的生产部署模式。
核心优势
- 架构简化:无需独立部署、监控、备份 ZooKeeper;
- 性能提升:元数据变更吞吐提升 5–10 倍,延迟更低;
- 高可用增强:基于 Raft 协议,选举更快、防脑裂;
- 云原生友好:StatefulSet 部署更简单,适合 Kubernetes;
- 统一运维:日志、监控、告警全部集中于 Kafka。
注意:KRaft 仅改变元数据管理方式,消息存储、副本机制、ISR 等数据平面逻辑完全不变。
二、KRaft 架构模式
KRaft 支持两种部署模式:
| 模式 | 说明 | 适用场景 |
|---|---|---|
| Combined Mode | 单节点同时承担 Broker + Controller 角色 | 中小集群(≤ 20 节点) |
| Dedicated Mode | Controller 与 Data Broker 物理分离 | 超大集群(> 20 节点)或高安全要求 |
三、Combined Mode 架构与工作流程
架构图
在 Combined Mode 中,
C1 = B1,C2 = B2,C3 = B3,即角色合一。
工作流程步骤
-
集群启动
- 所有节点启动 Kafka 服务;
- 每个节点根据
process.roles=broker,controller初始化双重角色; - Controller 模块尝试加入 Raft Quorum。
-
Raft 选举
- 节点通过
CONTROLLER监听器(如 9093 端口)通信; - 选举出一个 Active Controller(Leader);
- 其余节点成为 Follower,仅同步元数据日志。
- 节点通过
-
Broker 注册
- 每个 Broker 向 Active Controller 发送注册请求;
- Active Controller 将 Broker 信息写入 Metadata Log(内部 Topic
__cluster_metadata); - 日志通过 Raft 协议复制到所有 Follower。
-
元数据变更(如创建 Topic)
- 客户端请求 → 任意 Broker → 转发至 Active Controller;
- Active Controller 生成元数据变更记录,追加到 Metadata Log;
- 日志复制成功后,广播新元数据给所有 Broker。
-
消息读写(数据平面)
- Producer/Consumer 连接任意 Broker;
- 若非目标分区 Leader,Broker 返回 Redirect;
- 客户端直连 分区 Leader Broker,不经过 Controller;
- 消息路径完全独立于控制平面。
-
故障恢复
- Active Controller 宕机 → Raft 心跳超时 → 触发新选举;
- 新 Leader 从本地 Metadata Log 恢复全量状态;
- 继续提供元数据服务,业务无感知。
关键结论:
- 控制平面:Client → Broker → Active Controller → Metadata Log(Raft 复制);
- 数据平面:Client ↔ Partition Leader Broker(直连,高效);
- Controller 不参与消息收发。
四、Raft Controller 选举流程详解
KRaft 使用标准 Raft 协议实现 Controller 高可用。
触发条件
- 集群首次启动;
- Active Controller 宕机或网络隔离;
- Follower 在
election.timeout.ms(默认 1–2 秒,随机化)内未收到心跳。
详细步骤
步骤 1:Follower 转为 Candidate
- 某 Follower(如 Controller 2)未收到 Leader 心跳;
- 自增 term(任期)(如 1 → 2);
- 投票给自己;
- 向其他 Quorum 成员发送
RequestVote RPC,包含:- 自身 term;
- 最后一条日志的 index 和 term。
步骤 2:接收投票
- 其他节点判断:
- 自身 term ≤ 请求 term;
- 请求者日志 不比自己旧;
- 若满足,则投出 唯一一票;
- 返回
VoteGranted = true。
步骤 3:赢得选举
- Candidate 收到 多数派投票(3 节点需 2 票);
- 转为 Leader;
- 向所有 Follower 发送空
AppendEntries(心跳),宣告领导权。
步骤 4:维持领导
- Leader 定期(如每 500ms)发送心跳;
- Follower 收到后重置选举计时器;
- 只要心跳正常,就不会发起新选举。
步骤 5:处理旧 Leader 回归
- 原 Leader 恢复但 term 已过期;
- 收到新 Leader 的
AppendEntries后,自动降级为 Follower; - Raft 协议天然避免脑裂。
Raft 安全性保障(KRaft 实现)
- Election Safety:任一 term 最多一个 Leader;
- Log Matching:相同 index + term 的日志内容一致;
- Leader Completeness:已提交日志必存在于未来 Leader 中;
- Pre-Vote(可选):防止网络抖动引发无效选举。
五、KRaft 配置详解
1. 生成集群 ID(首次部署必需)
CLUSTER_ID=$(bin/kafka-storage.sh random-uuid)
echo $CLUSTER_ID # 保存用于格式化
2. server.properties(Combined Mode 示例)
# ===== 基础身份 =====
process.roles=broker,controller
node.id=1
# ===== 网络监听 =====
listeners=PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093
inter.broker.listener.name=PLAINTEXT
controller.listener.names=CONTROLLER
advertised.listeners=PLAINTEXT://kafka1.example.com:9092
# ===== Controller Quorum =====
controller.quorum.voters=1@kafka1:9093,2@kafka2:9093,3@kafka3:9093
# ===== 存储目录 =====
log.dirs=/data/kafka/data
metadata.log.dir=/data/kafka/metadata # 强烈建议独立磁盘
# ===== 主题默认配置 =====
num.partitions=6
default.replication.factor=3
min.insync.replicas=2
# ===== 安全关闭 =====
controlled.shutdown.enable=true
3. 初始化存储目录(每个节点执行)
bin/kafka-storage.sh format -t <CLUSTER_ID> -c config/server.properties
4. 启动服务
bin/kafka-server-start.sh config/server.properties
# 无需启动 ZooKeeper!
六、关键配置参数说明
| 参数 | 默认值 | 说明 | 生产建议 |
|---|---|---|---|
process.roles |
— | 节点角色 | broker,controller(Combined) |
node.id |
— | 节点唯一 ID | 与 voters 中 ID 一致 |
controller.quorum.voters |
— | Quorum 列表 | 格式:id@host:port,... |
metadata.log.dir |
同 log.dirs |
元数据日志目录 | 独立 SSD 磁盘 |
metadata.max.retention.bytes |
Long.MAX | 元数据日志保留大小 | 按需设置(如 1GB) |
controller.quorum.election.timeout.ms |
1000–2000 | 选举超时(随机) | 无需调整 |
七、运维与监控
1. 查看 Quorum 状态
bin/kafka-metadata-quorum.sh --bootstrap-server kafka1:9092 describe --status
输出示例:
ClusterId: a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8
LeaderId: 1
VoterEndpoints: 1@kafka1:9093,2@kafka2:9093,3@kafka3:9093
HighWatermark: 12345
2. 查看元数据日志(调试)
bin/kafka-dump-log.sh --cluster-metadata-decoder \
--files /data/kafka/metadata/00000000000000000000.log
3. 关键监控指标
| 指标 | 说明 |
|---|---|
ActiveControllerCount |
应恒为 1 |
QueuedUnsentRequests |
Controller 请求积压 |
AppendRecordsRate |
元数据写入速率 |
MetadataLogSize |
元数据日志大小(应定期快照压缩) |
八、常见问题与故障处理
| 问题 | 现象 | 解决方案 |
|---|---|---|
| 无法选举 Leader | ActiveControllerCount = 0 |
检查 Quorum 节点数 ≥ 半数 |
| Broker 无法注册 | 日志报 “NotControllerException” | 检查 node.id 唯一性、网络通 CONTROLLER 端口 |
| 元数据日志损坏 | 启动失败,报 “Corrupt snapshot” | 从 Snapshot 恢复,或重建集群(需备份数据) |
| 客户端连接失败 | 报 “UnknownTopicOrPartition” | 确认 Active Controller 正常,元数据已同步 |
九、总结与最佳实践
推荐场景
- 新项目:强制使用 Kafka 3.5+ + KRaft;
- 容器化部署:Kubernetes StatefulSet + Combined Mode;
- 大规模集群:Dedicated Controller Mode + 独立元数据盘。
注意事项
- 不可原地升级:ZooKeeper 模式需重建集群才能迁移到 KRaft;
- 备份策略:定期备份
metadata.log.dir和 Topic 数据; - 监控重点:Quorum 健康度、元数据日志大小、选举频率。
延伸阅读
更多推荐



所有评论(0)