Kafka 面试题(2026-06-18)
【面试题】1. Kafka 线上需要监控哪些核心指标?消费滞后(Lag)怎么告警?
【标准答案】Kafka 监控分三层。Broker 层:关注 CPU、内存、磁盘 IO、网络吞吐和 GC 情况,尤其是磁盘 util% 不能长期高于 80%,不然写入延迟飙升。系统层面还有 underReplicatedPartitions(未同步副本分区数)大于 0 就要告警,说明有副本掉队。分区层:重点关注 Leader 分布是否均衡、ISR 缩容次数、分区磁盘使用率。消费者层:消费滞后量(Consumer Lag)是最关键的指标,它直接告诉你消费者跟不跟得上生产者。一般用 kafka-consumer-groups 命令行或者 Burrow(LinkedIn 开源)做 Lag 监控,Burrow 好在对 Lag 做滑动窗口评估,能区分"临时波动"和"持续积压"。告警策略别设一个固定阈值——QPS 高的时候 Lag 天然大,应该按比例告警(比如 Lag 超过 5 分钟的消息量才报警),或者 Burrow 的"消费者状态变 Warning 就触发"。监控工具推荐 Prometheus + Grafana + Kafka Exporter 这一套,配置灵活图形好看。
【面试题】2. Kafka 分区 Leader 选举什么时候触发?流程是怎样的?
【标准答案】Leader 选举的触发条件有三个:一是 Leader Broker 宕机或网络故障心跳超时,Controller 检测到后触发;二是运维主动执行分区重分配;三是 Administrator 手动触发 Preferred Leader Election 做负载均衡。流程:Controller 从 ZooKeeper/KRaft 感知到 Broker 上下线 → 找出受影响的 Leader 分区 → 遍历每个分区,从 ISR 里选一个存活副本当新 Leader → 把新 Leader 和 ISR 信息写入 ZK/元数据日志 → 通过 LeaderAndIsr 请求广播给相关 Broker,通知 Follower 开始从新 Leader 同步。选举顺序上 Kafka 默认选 ISR 列表里第一个副本(即 AR 顺序),不是随机、也不是选最同步进度最好的。整个选举过程依赖 Controller 单线程处理,分区太多(万级)时选举会有延迟。线上尽量保持 ISR 稳定,减少不必要的 Leader 切换,因为切 Leader 期间该分区短暂不可写。
【面试题】3. ConsumerRebalanceListener 有什么用?三个回调分别在什么时候触发?
【标准答案】ConsumerRebalanceListener 是 Kafka 消费者暴露的一个钩子接口,让你在 Rebalance 前后做自定义逻辑。主要有两个方法(Kafka 2.4+ 多了第三个)。onPartitionsRevoked(再均衡前回调):在分区被回收之前触发,你要在这里提交位移——重要!这个回调执行完之前消费者不会释放分区,所以要快。典型用法是 flush 缓存、提交最后一批位移,清理本地状态。onPartitionsAssigned(再均衡后回调):新分区分配完成后触发,在这里可以 seek 到指定位移、初始化本地缓存、预热连接。onPartitionsLost(Kafka 2.5+):分区被强制回收时触发(比如心跳超时被踢出组),此时已经不能再提交位移了,只能做清理。实际场景:如果你用本地内存做一些聚合计算,再均衡前把计算结果持久化到 DB,新消费者在 assigned 回调里加载回来,保证状态不丢。另一个场景是 seek 到指定时间点做数据重放。
【面试题】4. Kafka 幂等生产者底层怎么实现的?PID 和 Sequence Number 各起什么作用?
【标准答案】幂等生产者解决的是"同一消息在 Broker 不会写多次"的问题,防止重试造成的重复。实现靠两个核心机制:PID(Producer ID)和 Sequence Number。启动时生产者向 Broker 申请一个全局唯一的 PID,这个 PID 在生产者生命周期内不变(重启会换新 PID)。生产者对每个发到分区的消息分配一个单调递增的 Sequence Number,从 0 开始。Broker 端在内存中为每个 PID+分区维护最近的 5 个 Sequence Number,收到消息时检查:如果 SeqNum 比上次提交的刚好大 1,顺序写入;如果 SeqNum 小于等于上次提交的,说明是重试的旧消息,直接丢弃;如果 SeqNum 比上次大超过 1,说明丢消息了,抛 OutOfOrderSequenceException。注意幂等只保证同一个分区内同一生产者会话的不重复,跨分区、生产者重启后就不保证了。开启方式只要 enable.idempotence=true,max.in.flight 自动变成 5(2.0+),同时 acks 强制设成 all,retries 设成 MAX。面试官爱追问:PID 怎么生成的?——老版本存 ZK,新版本由 Transaction Coordinator 分配。
【面试题】5. ISR 频繁伸缩(抖动)是什么原因?线上怎么处理?
【标准答案】ISR 抖动就是说 Follower 被踢出又快速加回来,反复横跳。通常三个原因:一、Follower 所在 Broker 的磁盘 IO 打满了,拉取 Leader 数据变慢,超过 replica.lag.time.max.ms(默认 30 秒)被踢,IO 恢复后追上再加回。二、网络抖动导致 Follower 和 Leader 之间拉取请求偶尔超时。三、Leader 端写入 QPS 波动大,高峰期写入速度超过了 Follower 的同步能力,Follower 短期掉队被踢,流量回落后又追上。ISR 抖动的危害:每次 ISR 变更 Controller 都要广播元数据更新,频繁变更给 Controller 和网络压力量大;如果 ISR 缩到只剩 Leader 且 min.insync.replicas 没配,acks=all 退化成 acks=1,丢数据风险。处理办法:优先加大 replica.lag.time.max.ms 到 60 秒甚至 120 秒,给 Follower 更多追赶时间;检查 Follower Broker 的磁盘 IO 状况,如果持续高压就扩容或迁移分区;降低 Leader 写入压力——增加分区数分散写入。核心思路:让 Follower 有更多容错时间,不轻易被踢。
【面试题】6. 生产者端关键性能参数怎么调优?batch.size、linger.ms、buffer.memory 怎么配合?
【标准答案】生产者性能调优核心是平衡吞吐和延迟,围绕"攒批发送"做文章。batch.size(默认 16KB):控制一个批次能攒多少消息再发送。设太小子多条多网络开销大,吞吐低;设太大延迟高。一般根据单条消息大小设——消息比较大(10KB)就设 256KB 甚至 512KB,把小消息的设 64KB。linger.ms(默认 0):生产者等多久凑满一个批次再发,是延迟换吞吐的关键参数。设 5-10ms 能在几乎不增加感知延迟的情况下把吞吐提上来。设 0 就是有消息立刻发,低延迟但也没批处理。buffer.memory(默认 32MB):生产者端缓存池,攒批消息暂存这里。满了 send() 会阻塞或抛异常。如果 max.block.ms 阻塞频繁,说明 buffer 不够,加大到 128MB。这三个配合:batch.size 决定每批的体量,linger.ms 决定等待的时间窗口,buffer.memory 决定总容量池。还有一个 compression.type,线上推荐 lz4 或 snappy——lz4 压缩快、CPU 省,snappy 压缩比适中,不要用 gzip,太吃 CPU。最终口诀:吞吐优先拉大 batch+加 linger,低延迟优先缩 batch+0 linger。
【面试题】7. Kafka 日志清理策略 Delete 和 Compact 的区别?Compact 的实现原理和坑有哪些?
【标准答案】Delete 策略:按时间(retention.ms)或大小(retention.bytes)自动删除过期日志分段,简单粗暴,适合日志、埋点类数据,只关心近期的。Compact 策略:不按时间来删,而是按消息 Key 去重——同一个 Key 只保留最新一条消息,旧的值被"压缩"掉。原理是后台 LogCleaner 线程定期扫描日志分段,读出来按 Key 分组,把每个 Key 的最新值写入新文件,旧分段删除。实际过程中有一个"清理点"(Dirty Ratio),log.cleaner.min.cleanable.ratio 默认 0.5,脏消息超过 50% 才清理。适合场景:数据库 CDC 同步——只需要每个 Key 最新状态,不需要历史记录;Kafka 内部 的 __consumer_offsets Topic 就是用 Compact 存的位移。
几个坑:一、Key 为 null 的消息永远不会被 Compact,全部保留,时间长了占满磁盘;二、Compact 不会立即删除,需要等清理线程跑完一轮,实际可能延迟数分钟;三、Compact 只去重不掉头,最新一条消息始终保留,哪怕它已经 N 年前的数据,所以常配合 delete.retention.ms 给一个兜底删除时间。
【面试题】8. 分区 Leader 频繁切换(Leader Election Storm)怎么排查治理?
【标准答案】Leader Election Storm 是指短时间内分区 Leader 高频切换,对集群稳定性杀伤极大。排查分四步。第一步看 Controller 日志:zookeeper.session.timeout.ms 是否触发导致 Controller 频繁重新选举,如果是,可能 Controller 所在 Broker GC 严重或网络延迟大,先解决 GC 问题,再加 session.timeout。第二步看 Follower 的 fetch 线程:如果大量 Follower 拉取超时被踢出 ISR 又加回,Leader 在 ISR 成员变化时可能触发重选举——加大 replica.lag.time.max.ms 和 replica.fetch.wait.max.ms。第三步看 Broker 的系统指标:是不是有 Broker 磁盘 IO 打满、CPU 长期 100%——导致无法及时响应心跳被 ZK/Controller 判定为下线。第四步看网络:机架交换机是否有丢包,用 ping -f 或 iperf 测一下。治理层面:配置 unclean.leader.election.enable=false,不允许 ISR 外副本选 Leader;合理设置分区数,不要让 Controller 管理太多分区;做 Broker 级别的资源隔离,避免一个 Broker 同时是 Controller 又扛高流量分区。关键原则:Leader 切换的根因从来不是 Kafka 本身,而是底层资源问题。
【面试题】9. 机架感知(Rack Awareness)原理是什么?跨机房部署怎么配?
【标准答案】机架感知是让 Kafka 在分配副本时,知道每个 Broker 在哪个物理机架上,尽量把同一个分区的副本分散到不同机架。原理很简单:给每个 Broker 配置 broker.rack 参数,指定机架 ID(比如 rack1、rack2),Kafka 的副本分配算法就会保证一个分区的副本不在同一个 rack 上,避免单个机架断电或交换机故障导致整个分区副本全挂。配置方式:server.properties 里加 broker.rack=your-rack-id,重启生效,已经存在的分区不会自动重新分配,需要手动执行 kafka-reassign-partitions.sh 迁移。跨机房部署的进阶玩法:把 rack 扩展为"可用区"概念——同城两机房,主副本在 A 机房,从副本在 B 机房,这样 A 机房挂掉 B 机房的 Follower 能立刻选为 Leader,RTO 控制在秒级。跨机房要注意:一、网络延迟会增加副本同步时间,replica.lag.time.max.ms 要设大一些;二、两个机房间带宽要够,避免 ISR 频繁收缩;三、min.insync.replicas=2 保证至少跨机房有一个副本确认。MM2 做异地多活时同样要配好机架感知。
【面试题】10. Kafka 消息格式怎么设计?为什么推荐 Avro + Schema Registry?
【标准答案】消息格式设计是 Kafka 落地最容易踩的坑。最差的做法是用 JSON 纯文本:可读性好但体积大、没类型校验、Schema 演进全靠上下游口头约定,Producer 加了字段 Consumer 解析就炸。推荐方案是用 Avro 序列化 + Schema Registry 做 Schema 管理。Avro 是二进制序列化协议,体积比 JSON 小 3-5 倍,序列化速度快 3 倍以上,而且自带 Schema 不需要像 Protobuf 那样要预编译。Schema Registry 解决的核心问题是 Schema 演进管理:生产者写入消息时带上 Schema ID,消费者根据 Schema ID 去 Registry 拉取对应版本的反序列化,做到前后兼容。版本演进规则:FORWARD(新 Schema 兼容旧 Consumer)、BACKWARD(旧 Producer 兼容新 Consumer)、FULL(双向兼容)。线上强制 FULL 兼容最安全。流程是:定义 .avsc Schema 文件 → CI 阶段自动注册到 Schema Registry → 编译生成 Java 类 → 业务代码直接用类型安全的对象,避免了手工拼 JSON 的各种低级错误。大公司基本都这套,小项目如果觉得运维重可以用 JSON + 业务约定凑合,但只要消息格式会演变、有多个上下游,强烈建议上 Avro。
生成时间:2026-06-18 22:24 覆盖考点:监控与运维、副本管理(Leader选举)、消费者(RebalanceListener)、幂等性(PID+SeqNum)、ISR抖动、性能调优(生产者)、消息存储(Compact)、故障排查(Leader风暴)、高可用(机架感知)、落地实践(Avro+Schema Registry)