Kafka 常见面试题
核心架构
| 概念 | 说明 |
|---|---|
| Topic | 逻辑主题 |
| Partition | 物理分片;并行与顺序的基本单位 |
| Offset | 分区内单调递增;消费进度 |
| Broker | 存储与服务节点 |
| Leader / Follower | 分区 Leader 读写;Follower 同步 |
| ISR | 与 Leader 同步在阈值内的副本集合 |
| Consumer Group | 组内一个分区只分给一个消费者 |
| KRaft | 内置 Raft 管理元数据;4.0+ 无 ZooKeeper |
Consumer Group A Consumer Group B
C0 → P0 C0 → P0,P1,P2(独立消费)
C1 → P1
C2 → P2
规则:同组消费者数 ≤ 分区数;多则空闲。不同组互不影响。
为什么 Kafka 快
| 机制 | 说明 |
|---|---|
| 顺序写磁盘 | 追加日志,顺序 I/O 接近内存带宽 |
| Page Cache | 依赖 OS 页缓存,Broker 少拷贝 |
| Zero Copy | 消费端 sendfile 直传网卡 |
| 批量 | Producer batch.size、linger.ms |
| 分区并行 | 多 Partition 读写 |
| Pull 模型 | 消费者按能力拉,避免推爆慢消费者 |
存储与回溯
- 每个 Partition = 追加写日志 + Log Segment 滚动
retention.ms/retention.bytes过期删除- Compact Topic:同 key 保留最新(配置、CDC 状态)
- Offset 存
__consumer_offsets
生产者可靠性
acks | 含义 | 风险 |
|---|---|---|
0 | 不等确认 | 可能丢 |
1 | Leader 确认 | Leader 宕机未同步可能丢 |
all / -1 | ISR 全部确认 | 最可靠;配合 min.insync.replicas |
acks=all
retries=3
enable.idempotence=true # 幂等 Producer(单分区有序去重)事务 Producer:跨分区原子写 + 与消费 EOS(read_committed)。
消费语义
| 语义 | Kafka 实现 |
|---|---|
| At Most Once | 先 commitSync offset 再处理 |
| At Least Once | 先处理再提交 offset(默认常见) |
| Exactly Once | 幂等消费 + 事务 + read_committed |
手动提交:enable.auto.commit=false,业务成功后 commitSync。
Rebalance(再均衡)
触发:消费者入退组、心跳/poll 超时、分区数变、订阅变。
过程:暂停消费 → 重新分配分区 → 恢复(STW 式,影响延迟)。
优化:cooperative-sticky 增量协议;静态成员 group.instance.id 减少重启 rebalance。
反模式:poll 循环内长时间 DB/HTTP → 触发 max.poll.interval.ms 被踢出组。
顺序与 Key
- 分区内有序;跨分区无序
- 相同
key→ 同一分区(默认murmur2(key) % partitions) - 全局有序:单分区(吞吐受限)
副本与 Leader 选举
Producer ──acks=all──► Leader
├── Follower (ISR)
└── Follower (非 ISR,落后多)
| 场景 | 说明 |
|---|---|
| Follower 落后 | 踢出 ISR |
| Leader 宕机 | 从 ISR 选新 Leader |
| ISR 为空 | unclean.leader.election.enable=false(生产推荐)避免丢数据 |
堆积(Lag)排查
kafka-consumer-groups.sh --describe看 LAG- 消费者是否存活、是否处理过慢
- 扩容消费者(≤ 分区数)或 增加分区(需规划 key)
- 临时限流生产、非核心消费者降级
Kafka vs RabbitMQ(简)
| Kafka | RabbitMQ | |
|---|---|---|
| 模型 | 日志 / Topic | 队列 / Exchange 路由 |
| 回溯 | offset 任意重放 | 消费即删(可 TTL) |
| 吞吐 | 极高 | 中 |
| 延迟 | ms | 更低(μs 级) |
| 适用 | 流、日志、CDC | 任务、复杂路由 |
常见面试题
Q:Consumer 数量大于分区数?
A:多余的空闲,不消费。
Q:如何保证消息不丢?
A:acks=all + min.insync.replicas≥2 + 消费处理完再提交 offset + 副本持久化。
Q:重复消费怎么处理?
A:业务幂等;Kafka 事务 + 幂等 Producer 只解决生产侧重复。
Q:KRaft 是什么?
A:用内置 Raft quorum 存元数据,去掉 ZooKeeper,简化运维、支持更大规模分区。