Kafka 面试题(2026-06-18)
【面试题】1. Kafka 生产者怎么决定一条消息发到哪个分区?默认分区器和自定义分区器分别怎么用?
【标准答案】生产者决定分区靠 Partitioner 接口。默认分区器逻辑分两种情况:一、消息指定了 Key——对 Key 做 murmur2 hash,然后用 hash 值对分区数取模,保证相同 Key 永远去同一个分区,天然支持局部有序。二、消息没指定 Key——老版本用轮询,新版本(2.4+)用"粘性分区"(Sticky Partitioner),把一批消息先发到同一个分区,批满了再换下一个分区。这样比轮询攒批效率高得多,因为同一个分区的消息能凑成大 batch 压缩后一次发走。自定义分区器场景:比如你需要按业务规则路由——订单消息按订单金额区间分到不同分区(大额订单单独分区优先处理),或者按用户所属地域就近落盘。实现就是实现 Partitioner 接口的 partition() 方法,返回分区编号,配置里设 partitioner.class 指向你的类。坑:分区数变了 Key 的 hash 取模结果会变,存量相同 Key 的消息就可能散到不同分区——设计阶段分区数尽量一步到位。
【面试题】2. 消费者参数 auto.offset.reset 的 earliest、latest、none 三种模式有什么区别?分别适用什么场景?
【标准答案】这个参数只在消费者找不到已提交位移时生效(比如新消费组第一次启动、位移过期被清理、或手动重置后)。earliest:从分区最早的消息开始消费,相当于全量回放。适用于新业务第一次接入需要消费历史所有数据、或者数据修复要全量重算的临时任务。latest:从分区最新位置开始消费,跳过所有历史数据,只消费新来的消息。适用于只关心实时数据的在线业务——今天部署的服务不需要管昨天的数据。none:找不到位移直接抛异常,强制你必须手动处理。这是最安全的选择,防止你"不知道发生了位移丢失就默默从 earliest/latest 开始了"。DBA 和关键数据处理推荐 none——有一次生产事故就是消费组位移因 retention 过期被清理,默认 earliest 导致几千万条历史消息被重复消费。另外如果你已经提交了位移,就算提交的是 5 天前的,auto.offset.reset 也不触发——它只在"完全找不到位移"时才激活。
【面试题】3. Kafka 的消息压缩是怎么做的?生产者压缩和 Broker 压缩有什么区别?选 gzip、snappy、lz4 还是 zstd?
【标准答案】Kafka 的压缩在生产者端做——消息攒成 batch 后,对整批消息做压缩,Broker 收到后原样存盘,不解压也不重压(除非配了 compression.type=producer 且两端一致)。消费者拉取时也是整批拉,消费者自己解压,全程 Broker 不动压缩内容。这样 CPU 开销在两端、不在 Broker。四选一指南:gzip 压缩率最高(通常 4-6 倍),但 CPU 负担重、速度慢,适合带宽紧张、消息要长期存储的场景;snappy 是 Google 出的,压缩率中等(2-3 倍)、速度最快,适合低延迟高吞吐场景;lz4 压缩率和速度介于中间,但解压极快,消费端友好;zstd 是 Facebook 出的,压缩率接近 gzip 但速度快得多,是下一代默认选择,Kafka 2.1+ 原生支持。线上推荐:一般业务用 lz4,延迟敏感用 snappy,存储优先或保留时间长用 zstd。注意 Broker 端的 compression.type 设 producer 就行,别让 Broker 重复压缩浪费 CPU。还有坑:不同版本的压缩格式混用可能不兼容,生产升级时所有消费者也要同步升级客户端。
【面试题】4. Kafka 副本同步中 HW(高水位)和 LEO(日志末端位移)是怎么协同推进的?为什么 Follower 的 HW 总是落后 Leader?
【标准答案】LEO 是"下一条将要写入消息的 offset",每个副本自己维护,写入一条就 +1。HW 是"消费者能读到的最新 offset",所有副本共享。推进逻辑:Leader 维护所有 Follower 的 LEO(通过 Fetch 请求上报),Leader 的 HW = min(Leader的LEO,所有ISR内Follower的LEO)。也就是说 Leader 的 HW 等于所有同步副本中最慢的那个 LEO。Leader 把这个 HW 通过下一轮 Fetch 响应带回给 Follower,Follower 据此更新自己的 HW。所以 Follower 的 HW 天然落后于 Leader,因为它是从 Leader 的响应里"听说"的,有一轮网络往返的延迟。这解释了为什么 acks=all 时生产者延迟取决于最慢的 ISR——HW 被最慢的副本拖住了。面试官爱追问:"如果所有 Follower 都挂了只剩 Leader,HW 还会推进吗?"——会,因为 ISR 里只剩 Leader 自己,min(ISR的LEO) = Leader的LEO,HW 正常推进。这也是为什么 min.insync.replicas=1 等于没保护。
【面试题】5. 消费者的三个超时参数 session.timeout.ms、heartbeat.interval.ms、max.poll.interval.ms 分别管什么?调错了会怎样?
【标准答案】这三个参数是消费者健康检查的三道保险。session.timeout.ms(默认 45s):消费者和 GroupCoordinator 之间的心跳超时——Coordinator 在这个时间内没收到心跳,就把消费者踢出消费组触发 Rebalance。heartbeat.interval.ms(默认 3s):心跳发送间隔,必须小于 session.timeout.ms,一般设成 1/3。max.poll.interval.ms(默认 5min):两次 poll() 之间的最大间隔——超过这个时间说明消费者处理逻辑太慢,Coordinator 认为它卡死了,主动踢出。常见调错:一、max.poll.interval.ms 设太短、业务处理要 30s 结果 10s 就被踢,导致消费者反复加入退出、频繁 Rebalance 消费停顿;二、session.timeout.ms 设太小(比如 6s),一次 GC 停顿就触发 Rebalance;三、heartbeat 和 session 的比值不合理——heartbeat 设 1s 太激进浪费网络,设 10s 且 session 只有 12s 的话,一次丢包就超时。线上推荐:session 60s、heartbeat 20s、max.poll.interval 根据业务最长处理时间×2。还有,新版 Kafka 把 heartbeat 线程独立出来了,poll() 阻塞不会影响心跳发送——这个改进面试提到很加分。
【面试题】6. Kafka 为什么能跑到百万 TPS?零拷贝(Zero-Copy)在其中起了什么作用?
【标准答案】Kafka 高吞吐的底层秘密武器就是零拷贝。传统消费流程:Broker 从磁盘读数据到内核缓冲区→内核缓冲区拷贝到 JVM 堆→JVM 堆拷贝到 Socket 缓冲区→发网卡。四次拷贝两次 CPU 参与,消费者越多 CPU 越吃紧。零拷贝用 sendfile 系统调用:数据从磁盘到内核缓冲区后,直接 DMA 传输到网卡,跳过 JVM 堆,CPU 零参与,一次系统调用搞定。这样消费者再多也不吃 Broker CPU,吞吐瓶颈从 CPU 转移到了网络带宽和磁盘 IO。除了零拷贝,Kafka 高性能还有几个支柱:顺序写磁盘(比随机写快 100 倍)、PageCache 缓存热数据、攒批发送减少网络往返、消息压缩减少传输量。面试官追问"哪些场景零拷贝不生效?"——消息需要解密、需要消息转换(SMT)、SSL 加密传输等情况,数据必须进 JVM 堆处理,零拷贝就走不通了。这也是为什么 Kafka 对端到端加密和消息转换这类需求不太友好。
【面试题】7. Kafka 的 Exactly-Once 语义(精确一次)到底是怎么实现的?幂等生产者 + 事务之间是什么关系?
【标准答案】Exactly-Once 分两层。第一层幂等(Exactly-Once per Partition):开启 enable.idempotence=true,用 PID + SeqNumber 机制保证同一个生产者在单分区内不会重复写入。但 PID 在生产者重启后就换了,跨会话的重复挡不住。第二层事务(Exactly-Once across Partitions):给生产者绑定一个跨会话的 Transactional ID,Broker 通过这个 ID 把新 PID 和旧 PID 关联起来。事务流程:生产者 beginTransaction→发消息到多个分区(各分区标记 Pending)→发 commit 给事务协调器→协调器写 PREPARE_COMMIT 到 __transaction_state→再写 COMMIT→各分区把 Pending 消息变可见。如果中间宕机,协调器从 __transaction_state 恢复状态,要么 commit 要么 abort。幂等和事务的关系:幂等是事务的基石——事务的每次发送都带 PID+Seq,靠幂等兜底;事务在幂等之上加了跨分区原子性和会话恢复。一句话:幂等管"一条消息别重复",事务管"一批消息要么全成功要么全回滚"。实现 EOS 的参数:enable.idempotence=true + transactional.id 设唯一值 + acks=all。
【面试题】8. Kafka 3.x 用 KRaft 替代 ZooKeeper,架构上到底变了什么?现有 ZK 集群要不要迁移?
【标准答案】KRaft 的核心变化:元数据管理层从"外挂 ZK"变为"内建 Raft 共识"。老架构里 ZK 管 Broker 注册、Controller 选举、Topic/分区元数据,ZK 挂了集群就瞎了。KRaft 把元数据存在 Kafka 内部的 @metadata Topic 里,用 Raft 协议在 Controller 节点间复制,ZK 彻底下岗。带来的好处:一、运维简化——少维护一个 ZK 集群,不用纠结 ZK 和 Kafka 两个集群的版本兼容和监控;二、元数据一致性更强——ZK 是异步通知,Broker 可能拿到过时元数据,KRaft 是 Raft 线性一致读;三、可扩展性——ZK 的大集群瓶颈(几百万分区)在 KRaft 上不存在,元数据也在 Kafka 的日志模型下管理;四、启动更快——不用等 ZK 连接和 watch 注册。要不要迁移:新项目直接上 KRaft(3.3+ 生产可用,3.5+ 成熟);老项目如果 ZK 跑得稳定且没到瓶颈,不急迁移——迁移有风险,KRaft 模式不支持降级回 ZK。如果老项目受 ZK 瓶颈困扰(比如分区数 50 万+),建议规划迁移,灰度切。
【面试题】9. 线上一个大生产者发消息太快把某个 Broker 的磁盘和网络打满了,你怎么在不重启业务的前提下限流?
【标准答案】Kafka 有原生 Quota 机制,不需要重启业务。操作分三层。第一层动态配置——在 Broker 上开 Quota:kafka-configs.sh 对用户 client.id 或 user principal 设 producer_byte_rate(比如 50MB/s)和 request_percentage(请求占比)。改了立刻生效,Broker 对超配额请求返回 throttling 响应,生产者收到后自动降速,不丢消息。第二层客户端自适应——生产者的请求被节流后会退避,配合 buffer.memory 暂存消息,不会报错。第三层监控验证——看 kafka.server:type=ThrottleTimeMs 指标确认限流生效。如果没有开 Quota 机制(老版本),应急方案:在交换机或防火墙层对源 IP 做流量整形;或者临时降低生产者的 batch.size 和 linger.ms 手动削峰。长期治理:给每个客户端分配唯一 client.id,按业务等级设配额——核心高优业务配额高、批量离线任务配额低。配额的颗粒度可以到用户级别(SASL/SSL 认证),多租户集群必须搞。还要注意:throttle 不仅限生产者,消费者拉取也有 fetch quota,防止一个消费组把带宽抢光。
【面试题】10. Kafka Streams 和 Flink / Spark Streaming 有什么区别?什么时候该用 Kafka Streams 而不是引入 Flink?
【标准答案】Kafka Streams 是 Kafka 原生的流处理库,核心定位是"对流进 Kafka 的数据做轻量级实时处理",部署简单——就是个 Java 库,打成 jar 启动,不需要额外集群。Flink 和 Spark Streaming 是"独立的流计算引擎",能力更强但运维成本高——要搭 YARN/K8s 集群、管理 JobManager/TaskManager。区别表格化:Kafka Streams 适合场景——数据进出全是 Kafka(比如实时过滤、聚合、Join 两个 Topic),处理逻辑不复杂,团队不想维护第二套集群。Flink 适合——需要复杂事件处理(CEP)、精确一次状态持久化到外部存储、大规模窗口聚合、多数据源混合(Kafka + 文件 + 数据库 CDC)。具体决策思路:如果整个链路 90% 是 Kafka→处理→Kafka,先用 Kafka Streams 搞定,部署就是多起几个实例,水平扩展靠加实例,容错靠 Kafka 的位移管理。当 Kafka Streams 的状态大到需要外部存储(RocksDB 撑不住了)、或者需要跟 HBase/MySQL 做交互查询时,再迁到 Flink。不要在 Kafka Streams 上强行做它不擅长的事——比如复杂 CEP 和跨数据中心的状态管理。Kafka Streams 的 Interactive Query 特性也是亮点:可以直接查本地状态存储,不需要额外 Redis。
生成时间:2026-06-18 23:03 覆盖考点:生产者分区器原理、消费者偏移量重置(earliest/latest/none)、消息压缩机制(gzip/snappy/lz4/zstd)、副本同步HW与LEO推进、消费者心跳与三个超时参数、零拷贝(Zero-Copy)技术、Exactly-Once语义(幂等+事务)、KRaft模式vs ZK模式、Kafka配额与限流机制、Kafka Streams vs Flink/Spark Streaming对比