KafkaNotes

第 27 章:面试题精讲:50 个高频问题

zjc 于 2026-01-27 发布

这是《Kafka 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 本章按“基础 -> 原理 -> 性能运维 -> 场景设计”组织 50 个高频问题,答案追求面试可直接使用的深度与结构。建议先遮住答案自己回答,再对照补充。

27.1 基础篇

Q1. Kafka 是什么?能解决什么问题?

分布式事件流平台,兼具发布订阅、持久化存储与流处理三类能力。典型用途:系统解耦、异步削峰、日志/埋点管道、流计算、CDC 同步、事件驱动架构。回答时可强调它以“分区日志”为核心,消费不删数据,因此可回放、可多订阅。

Q2. Kafka 为什么快?

六件套:磁盘顺序写、页缓存、零拷贝(sendfile)、批量+压缩、分区水平扩展、消费者拉模式背压。再补一句:V2 消息格式用增量编码与 batch 级 CRC,进一步降低解析与存储成本。

Q3. Topic、Partition、Replica 的关系?

Topic 是逻辑类别;Partition 是并行与顺序的物理单位,每分区是一个只追加日志;Replica 是分区的副本,分 Leader/Follower,读写只走 Leader,Follower 只同步。

Q4. 为什么分区只能增加不能减少?

减少要处理已删除分区上的消息归属、key 哈希重分布、消费者位移迁移、副本删除时序等一致性问题,工程收益低风险高。Kafka 官方不支持;若有必要,走“新 topic 迁移 + 切流”。

Q5. Kafka 和 RabbitMQ 怎么选?

Kafka:海量日志/事件流、高吞吐、长期保留、回放、流处理生态。RabbitMQ:复杂路由、低延迟传统消息、请求回复型任务队列。定位上 Kafka 更像数据中枢,RabbitMQ 更像消息代理。

Q6. delete 和 compact 两种清理策略的区别?

delete 按 retention 滚动删除 segment,适合事件/日志。compact 按 key 保留最新值,适合状态快照、配置、CDC 最新值。可组合 compact,delete

Q7. 什么是 ISR?

与 Leader 保持同步的副本集合,判定标准是 replica.lag.time.max.ms 内追上 Leader。acks=all 等待的是 ISR 而非全部副本;min.insync.replicas 限制 ISR 最小数量。

Q8. LEO 和 HW 分别是什么?

LEO 是日志下一条待写入的 offset;HW 是所有 ISR 已同步的位置,消费者只能读到 HW 之前。Leader 切换与副本截断依赖它们(更精确的是 leader epoch)。

Q9. 消费组内外的消费语义?

组内一个分区只给一个消费者(竞争、负载均衡);组间各自独立消费全量(广播)。消费者数超过分区数时多余实例空闲。

Q10. 消费位移存在哪里?

内部 compact topic __consumer_offsets,默认 50 分区,key 为 group+topic+partition,value 为 offset 等元数据。

27.2 原理篇

Q11. 描述生产者发送流程。

主线程:拦截器 -> 序列化 -> 分区器 -> RecordAccumulator 攒批;Sender IO 线程按 Broker 合并发送;Broker 返回后执行回调。参数上 batch.size 控批大小,linger.ms 控等待,delivery.timeout.ms 控总期限。

Q12. 消息如何选分区?

显式指定优先;否则 key 非空用 murmur2(key) % 分区数;key 为空用粘性分区(先填满一个分区的 batch 再切换),兼顾均衡与批效率。

Q13. acks=0/1/all 的语义?

0:不等确认,可能丢;1:Leader 写入即返回,Leader 闪退未同步会丢;all:等 min.insync.replicas 个 ISR 副本确认,配合 RF=3/min ISR=2 最可靠。all 在 ISR=1 时退化为 1。

Q14. 幂等生产者的原理?

PID + epoch + 每分区单调 sequence。Broker 缓存最近 5 个 batch 序号:重复丢弃并返回成功,缺口报乱序。范围限单会话单分区,进程重启后不能防业务层重复。

Q15. 事务的原理?

transactional.id 定位事务协调器;initTransactions 注册并 fence 旧 epoch;提交两阶段(PrepareCommit + 分区 marker);read_committed 消费者由 LSO 控制可见性。适合跨分区原子写与 consume-transform-produce。

Q16. Kafka 的 exactly once 范围是什么?

默认幂等防发送重试重复;事务保证 Kafka 到 Kafka 链路的原子性;涉及外部系统要业务幂等(唯一键/状态机/本地事务)配合。不能说“开了 EOS 就万事大吉”。

Q17. Rebalance 的触发条件与流程?

触发:成员变化、订阅变化、分区数变化。流程:FindCoordinator -> JoinGroup(选组 leader)-> 组 leader 算分配 -> SyncGroup 下发 -> Heartbeat 维持。generation 递增隔离旧成员。

Q18. 四种分配策略的区别?

Range 按 topic 切块可能不均;RoundRobin 全局轮询更均匀但要求订阅一致;Sticky 均衡且保留原分配减少迁移;CooperativeSticky 在 Sticky 上支持增量式,只停顿迁移分区,推荐新系统。

Q19. Rebalance 风暴怎么排查?

看被踢成员与时间点,对因处理:max.poll.interval 超时(降 max.poll.records/优化处理)、GC 停顿、心跳超时、发布频繁(静态成员)、订阅不一致。加协作式策略与告警。

Q20. Kafka 如何保证顺序?

分区内有序是底线;业务上同实体同 key;生产端开幂等且 in-flight<=5;消费端单线程或按 key 路由线程;避免扩分区破坏 key 连续性;必要时版本号拒绝旧事件。

Q21. 描述存储结构。

每分区一个目录,多个 segment(.log/.index/.timeindex),文件名为起始 offset。索引是稀疏的(每 4KB 日志一条),查找用二分索引 + 小范围顺序扫描;leader-epoch-checkpoint 支持一致性。

Q22. 零拷贝是怎么回事?

消费 fetch 时用 sendfile,数据从页缓存直达网卡,跳过用户态拷贝与上下文切换;条件是无需服务端格式转换且通道未做用户态加密。

Q23. Leader epoch 解决什么问题?

解决基于 HW 截断在极端时序下的副本分叉:Follower 重启/追随时先按 epoch 向 Leader 查询权威位移,精确截断后再同步。

Q24. KRaft 与 ZooKeeper 模式的区别?

KRaft 把元数据放进 __cluster_metadata Raft 日志,多数派 commit 后各节点按序回放;不再有 ZK 双写窗口,运维一套系统,Controller 切换更快。

Q25. __consumer_offsets 的 key/value 是什么?为什么 compact?

key=group+topic+partition,value=offset+metadata 等;每个位置只需最新值,compact 让体积可控,同时保留回溯能力。

27.3 性能与运维篇

Q26. 消息丢失怎么系统排查?

分层:Broker 是否写入(get-offsets/dump-log)、生产是否确认(回调/acks/flush)、消费是否跳过(committed offset/reset 记录)、保留期是否覆盖。修复靠 acks=all+RF3+minISR2+先处理后提交。

Q27. 重复消费的常见原因?

处理完未来得及提交就宕机;rebalance 后重复处理;commitAsync 失败未兜底;业务自己超时重发。处理:手动提交+同步兜底+下游唯一键/状态机。

Q28. 消息堆积怎么办?

先定位:写入突增、消费变慢、消费者减少、分区倾斜。手段:加消费者(<=分区数)、批量写下游、降级重逻辑、扩分区(注意 key 顺序)、业务确认后跳过过期数据。

Q29. 乱序怎么处理?

查 key 设计(同实体是否同 key)、生产重试乱序(幂等+in-flight<=5)、消费并发、扩分区、上游乱序。修复按根因对症。

Q30. ISR 频繁收缩的原因?

Follower 机器慢(CPU/磁盘/GC)、num.replica.fetchers 不足、Broker 间网络抖动、大迁移占 IO、replica.lag.time 过小。处置:调 fetcher、限流迁移、修硬件。

Q31. 怎么监控 consumer lag?

客户端 records-lag + 外部采集器(Burrow/kafka-lag-exporter,覆盖消费者挂掉场景)+ 命令巡检兜底。告警看 lag 趋势与追平时间(lag/消费速率)。

Q32. 分区数怎么定?

目标吞吐/单分区吞吐,向上取整并留余量;同时看消费并行度(消费者实例<=分区数)。分区不是越多越好:文件句柄、元数据、请求碎片、再平衡时间都会变差。

Q33. 生产者怎么调优?

吞吐:linger.ms 5-20、batch.size 32-64KB、zstd/lz4、buffer.memory 足够。延迟:linger=0、压缩 lz4。可靠:acks=all+幂等+回调。大消息拆引用。

Q34. 消费者怎么调优?

实例数<=分区数、批量处理、fetch.min.bytes 适度放大、max.poll.records 与处理时长匹配、静态成员+协作式 rebalance、下游异步化。

Q35. Broker 怎么调优?

看指标调:NetworkProcessorAvgIdle<30% 加网络线程;RequestHandlerAvgIdle<30% 加 IO 线程;ISR 落后加 replica fetchers;磁盘瓶颈加盘/条带化。页缓存优先于大 JVM 堆。

Q36. 为什么 Kafka 不建议开超大 JVM 堆?

性能核心在页缓存;堆大 GC 停顿风险高。通常 6-8GB 堆,剩余内存留给页缓存;网络/压缩用堆外内存,容器 limit 要留余量。

Q37. 扩容 Broker 后如何均衡数据?

kafka-reassign-partitions 生成->审查->执行->验证,可 throttle 限速分批迁移;之后 preferred leader 选举均衡 Leader;大规模用 Cruise Control。

Q38. Kafka 安全怎么做?

三层:TLS 加密、SASL/SCRAM 认证、ACL 授权(默认拒绝+最小权限)。凭据用 Secret/Vault,审计 ACL 变更。

Q39. 怎么迁移 Kafka 集群?

MirrorMaker 2 复制(注意 replication policy 与 offset checkpoint)、数据一致性校验、生产灰度切流、消费位移同步、观察期后停旧集群;全程保留回滚窗口。

Q40. 磁盘快满了怎么办?

应急:扩容、缩短低价值 topic 保留、清理僵尸 topic;根治:容量水位告警、生命周期治理、压缩策略、容量规划 review。磁盘 100% 会影响写入与元数据,优先级最高。

27.4 场景设计篇

Q41. 设计一个日志采集平台。

采集端(Filebeat/Fluent-bit)-> Kafka(按日志类型分 topic,分区按吞吐规划,zstd 压缩,保留 3-7 天)-> 批量消费者写 ClickHouse/ES + 归档 S3。要点:acks 可 1 换吞吐、批量写库、lag 与端到端延迟监控。

Q42. 订单系统如何不丢消息?

Outbox 本地事务 + relay 发送(acks=all、幂等、回调);topic RF=3/minISR=2;key=orderId 保序;消费先处理后提交 + 状态机幂等 + 重试/DLT;每日对账。

Q43. Kafka 怎么实现延迟队列?

原生不支持。常见方案:按延迟级别建 topic + 定时转发;时间轮库自研消费者;或用支持延迟的中间件承接该场景。说明权衡即可,别硬造。

Q44. 大消息(视频/大文本)怎么处理?

消息只放引用(对象存储 URL+摘要),内容放外部存储;必要时调 message.max.bytes/producer max.request.size/fetch 参数,但大消息会破坏批效率与页缓存命中率。

Q45. 如何实现广播和单播?

广播:不同消费组各自独立消费全量。单播(竞争):同一消费组内分区独占。注意组 id 管理:新组=新广播实例,同组扩容=负载均衡。

Q46. 消费端幂等怎么设计?

唯一事件表(event_id 唯一键 + 业务写同事务)、状态机拒绝非法迁移、upsert by 业务主键、乐观锁版本号。按业务后果选择强度。

Q47. 写库和发消息如何保证一致?

不要双写。用 Outbox:业务与 outbox 同一本地事务,relay 至少一次投递,消费端幂等。CDC 方案(Debezium 读 outbox/binlog)是变体。

Q48. 多租户 Kafka 怎么隔离?

共享 topic(字段/header 标识,弱)、独立 topic(ACL/quota,中)、独立集群(强)。配 quota 防大租户、header 带租户、大租户独立分区/topic 防热点。

Q49. Kafka 能当缓存或数据库用吗?

不能完全替代。它是为追加日志与顺序读优化的,点查/随机更新弱。可作物化状态源(KTable/compact topic)支撑流处理,但业务主存储仍应是 DB。

Q50. 什么场景不适合 Kafka?

强事务同步返回、低延迟 RPC 语义、复杂路由优先的小规模任务队列、超小消息量的简单系统(上 Kafka 运维成本不划算)、需要每条消息随机更新删除的场景。

27.5 回答技巧

  1. 先给结论,再给机制,最后给边界:例如“acks=all 一定不丢吗?不一定,当 ISR=1 时退化为…”;
  2. 带上参数与证据:能说出配置名、指标名、命令,可信度立刻不同;
  3. 结合事故或实验:讲一个你亲手复现的场景,胜过背十条概念;
  4. 主动提权衡:Kafka 的设计几乎都是取舍,展示你知道代价。

本章小结

面试的高分答案 = 准确概念 + 内部机制 + 参数证据 + 权衡意识。把第 10-20 章的原理章节吃透,这 50 个问题就能自然生长出你自己的版本。

思考题

  1. 面试中如何证明自己真的处理过 Kafka 生产问题?
  2. 为什么回答高可用问题时必须同时说明 acksmin.insync.replicas 和副本数?
  3. 消费端乱序、重复和丢失分别对应哪些机制?
  4. 如何解释 Kafka 页缓存与 JVM 堆内存的分配权衡?
  5. 设计题应按什么顺序展开容量、可靠性、治理和演进?