1. Kafka 集群核心组件
1.1 架构演进:ZooKeeper → KRaft
Kafka < 3.0(依赖 ZooKeeper):
ZooKeeper Ensemble (3/5 节点)
├── 存储元数据(Broker、Topic、Partition)
├── 管理 Controller 选举
└── 维护 ISR 列表
Kafka ≥ 3.3(KRaft 模式,推荐):
无 ZooKeeper
├── Controller 节点(Quorum,3/5 节点)
│ ├── 自管理元数据
│ ├── 使用 Raft 协议选举
│ └── 存储在内部 topic (__cluster_metadata)
└── Broker 节点(纯数据节点)
└── 更轻量,专注于消息存储
KRaft 消除了 ZooKeeper 运维负担,简化了部署,同时减少了元数据传播延迟。
1.2 Broker 角色
| 角色 | Kafka < 3.0 | Kafka ≥ 3.3 KRaft |
|---|---|---|
| Controller | 由 ZooKeeper 选举的特殊 Broker | 独立的 Controller 节点(Quorum) |
| Broker | 存储数据 + 可能兼任 Controller | 纯数据存储 |
| Quorum Leader | — | Controller 集群的 Leader |
2. 副本机制(Replication)
2.1 ISR(In-Sync Replicas)
Topic: orders (Partition 0, replication.factor=3)
Leader (Broker 101) ← 处理所有读写请求
│
├──→ Follower 1 (Broker 102) ← ISR 成员
│ 实时同步 Leader HW(High Watermark)
│
└──→ Follower 2 (Broker 103) ← ISR 成员
实时同步 Leader HW
ISR = {101, 102, 103}
如果 Follower 2 网络延迟过大:
ISR = {101, 102} (Broker 103 被踢出 ISR)
OSR = {103} (Out-of-Sync Replica)
关键参数:
| 参数 | 默认值 | 说明 |
|---|---|---|
replica.lag.time.max.ms | 30000 | 超出此时间未同步,踢出 ISR |
replica.lag.max.messages | 4000(已废弃) | 旧版按消息数判定 |
min.insync.replicas | 1 | 生产者 acks=all 时的最小同步副本数 |
2.2 数据可靠性公式
生产者配置:acks=all + min.insync.replicas=2
数据丢失条件:
- Leader 写入成功并复制给 ≥2 个 ISR
- 同时这 2 个副本都宕机(概率极低)
实际保障:
- 单副本宕机:无影响(剩余 ISR 仍有副本)
- ISR 中只剩 Leader:写入拒绝(ISR < min.insync.replicas)
- 这是一种"宁可不可用,也不丢数据"的设计
3. Leader 选举与故障转移
3.1 Leader 选举流程
场景:Broker 101(Leader)宕机
1. Controller 检测到 Broker 101 离线(通过心跳超时)
2. Controller 读取 Partition 0 的 ISR 列表:{101, 102, 103}
3. 从 ISR 中选最同步的 Follower 作为新 Leader(优先 ISR 中 LEO 最大的)
4. 更新元数据,通知所有 Broker 新 Leader
5. Producer/Consumer 自动从 Broker 101 切换到新 Leader(无需人工干预)
时间开销:
- 检测:zookeeper.session.timeout.ms(默认 18s)
- 选举:毫秒级
- 切换:客户端自动重连
3.2 Unclean Leader Election
配置:unclean.leader.election.enable
false(默认/推荐):
- 只有 ISR 中的副本能当选 Leader
- 如果 ISR 全挂 → 该 Partition 不可用 → 数据安全
true(不推荐):
- OSR 副本也能当选 Leader
- 可能丢失已确认写入的消息
- 适用:允许数据丢失、追求可用性的场景
4. KRaft 模式详解
4.1 为什么移除 ZooKeeper
| ZooKeeper 的问题 | KRaft 的解决 |
|---|---|
| 多系统运维(Kafka + ZK) | 单一系统,简化部署 |
| 元数据变更需 ZK 写入(~10ms) | 内存元数据,变更更快 |
| ZK 脑裂风险 | Raft 协议保证一致 |
| Controller failover 慢 | 更快的元数据恢复 |
| Topic 数量限制(~20万因 ZK 限制) | 可支持百万级 Partition |
4.2 KRaft 部署配置
# controller.properties
process.roles=broker,controller
node.id=1
controller.quorum.voters=1@localhost:9093,2@localhost:9093,3@localhost:9093
listeners=CONTROLLER://:9093
log.dirs=/tmp/kraft-logs
# 格式化存储(初始化集群)
kafka-storage.sh format -t <cluster-id> -c config/kraft/server.properties
# 启动
kafka-server-start.sh config/kraft/server.properties
5. 集群高可用最佳实践
5.1 部署架构
推荐生产部署:
跨可用区(AZ)部署:
AZ-A: Broker 1, Broker 2
AZ-B: Broker 3, Broker 4
AZ-C: Broker 5, Broker 6
副本分布策略:
- replica 0(Leader):AZ-A
- replica 1(Follower):AZ-B
- replica 2(Follower):AZ-C
可用区故障时:
AZ-A 故障 → Leader 漂移到 AZ-B 或 AZ-C
单 AZ 故障不影响数据可用性
KRaft Controller:
- 独立 3 台机器(或轻量 VM)
- 与 Broker 分离,避免资源争抢
5.2 关键配置检查清单
□ replication.factor >= 3
□ min.insync.replicas = 2
□ unclean.leader.election.enable = false
□ auto.leader.rebalance.enable = true(定期平衡 Leader)
□ log.flush.interval.messages = 10000(刷盘频率)
□ log.retention.hours 按业务设置(磁盘容量允许)
□ KRaft 模式下:controller.quorum.voters 正确配置
□ 跨 AZ 部署,网络延迟 < 5ms
□ 监控 ISR 收缩告警(ISR 缩小 = 风险信号)
延伸阅读
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。