主题
面试题蒸馏卡:Kafka
问题:Kafka 是什么?为什么快?怎么保证不丢不重?怎么保证顺序?高可用怎么实现?
高频问题与标准答
1. Kafka 是什么?为什么快?
- 定位:分布式流式处理平台 = 消息系统 + 持久化存储 + 流处理三合一。
- 快:顺序写日志(追加不寻址)+ PageCache 写缓存/读命中 + 零拷贝(
sendfile内核 cache→网卡,省两次用户态拷贝)+ 批量读写 + 批量压缩 + 分区分段稀疏索引。
2. 怎么保证消息不丢?(三段式)
| 段 | 答案要点 |
|---|---|
| 生产者 | 异步 + 回调捕获失败;acks=all(ISR 全写成功才算成功)+ retries 大值 |
| Broker | replication.factor ≥ 3、min.insync.replicas > 1(且 factor > min.insync,推荐 +1)、unclean.leader.election.enable=false |
| 消费者 | enable.auto.commit=false,业务处理成功再手动提交;auto.offset.reset=earliest |
3. 怎么保证不重复消费?
- 手动提交会带来「处理完没提交 → 重启重复消费」;Kafka 默认 at-least-once。
- 解法:消费端幂等(唯一业务键去重 / 外部存储记录已处理 offset);强一致场景上 exactly-once(offset 与消息处理原子化,事务性写入)。
4. 怎么保证消息顺序?
- 分区内有序(尾追加 + offset + 单消费者独占分区);Topic 全局无序。
- 保证顺序:① 单分区;② 同 key 同分区(如订单 ID 作 key)。分区数变更会破坏 key 映射。
5. 消费者组与 Rebalance 讲一下?
- 组内分区与消费者一一对应,一个分区只被组内一个消费者消费;消费者数 > 分区数会闲置。
- Rebalance:消费者/主题/分区数量变化触发;协调者(Coordinator)主导,JoinGroup(首个加入者当群主)→ 群主算分配 → SyncGroup 下发;重平衡期间整个组停摆(类似 GC STW)。
- 分配策略:Range(默认,按主题均分,多主题易不均)/ RoundRobin(跨主题轮询,均衡)/ Sticky(均衡优先 + 尽量保持上次分配,减少连接重建)。
6. 分区策略有哪些?(生产端)
- 轮询(key 为 null 时默认,最均衡)/ key hash 取模(同 key 同分区,保证该 key 有序)/ 随机 / 自定义
Partitioner/ 直接指定分区。
7. 副本机制:ISR / HW / LEO 是什么?
- AR=全部副本;ISR=与 Leader 同步的副本(唯一有资格当选 Leader 的);OSR=落后副本;AR=ISR+OSR。
- ISR 由 Leader 动态维护(
replica.lag.time.max.ms默认 10s)。 - LEO=各副本下一条待写位移;HW=ISR 最小 LEO,HW 前消息消费者可见。HW 是「Leader 取 Follower 最小 LEO 更新后回传」推进的。
8. 高可用怎么实现?Leader 挂了怎么办?
- 分区多副本 + ISR 选举:Leader 故障 → 从 ISR 中选新 Leader(unclean=false 时不同步副本没资格)。
- Controller(集群唯一,ZK 临时节点竞选 +
controller_epoch防过期请求)统一负责选举/元数据/重分配。 - 优先副本把 Leader 拉回 AR 首位,均衡负载。
9. Kafka 为什么不支持读写分离?
- 副本同步必有数据不一致窗口;读 Follower 多一次「主盘→从盘」拷贝有延时。Kafka 主写主读 + Leader 均匀分布本身已负载均衡。
10. 分区数越多越好吗?
- 不是。内存成本、文件句柄、副本复制线程、故障恢复时间(1 万分区 Controller 恢复约 +20s)四方面反噬。
11. 为什么抛弃 Zookeeper?
- 多一套系统运维贵;ZK 不适合高频读写(位移提交);规模大时元数据膨胀、Watch 延迟丢失。2.8.0 起 KRaft(Kafka 自己的 Raft)可完全替代。
追问链
- acks=all 就绝对不丢吗? 不是——ISR 只剩 Leader 时退化为 acks=1;unclean 选举开启时未同步副本仍可能当选。
- 手动提交 offset 会带来什么问题? 重复消费;所以必须配合幂等设计。
- 怎么增强消费能力? 加分区 + 消费者数对齐分区数;或消费端多线程处理(注意活锁:
max.poll.interval.ms超限会被踢出组)。 - Kafka 延迟队列怎么实现? 自研时间轮 TimingWheel + DelayQueue(插入删除 O(1),DelayQueue 做精准时间推进避免空推进),而非 JDK Timer/DelayQueue(O(nlogn));Netty/Akka/Quartz 同思路。
- 消息堆积了怎么办? 扩容分区 + 消费者;定位消费慢环节(DB/下游),必要时临时加大
max.poll.records并横向加实例。 - 和 RocketMQ 的区别? 消息模型几乎一致(Kafka 的 Partition = RocketMQ 的 Queue);Kafka 生态/吞吐更强,RocketMQ 事务消息更强。
常见误解
- ❌ "Kafka 能保证全局有序" —— 只能分区内有序。
- ❌ "消费者越多消费越快" —— 超过分区数就闲置,还有 Rebalance 风暴。
- ❌ "关闭自动提交就不会重复消费" —— 不丢与不重是跷跷板,手动提交把「丢」换成「重」,幂等才是终局解法。
- ❌ "Kafka 只是消息队列" —— 它是流式处理平台(存储 + 流处理是另两大功能)。