Skip to content

Kafka 面试题(2026-06-18) ​


【面试题】1. Kafka Connect 框架是什么?跟直接写 Producer/Consumer 相比有什么优势? ​

【标准答案】Kafka Connect 是 Kafka 自带的数据集成框架,专门做"外部系统↔Kafka"的批量数据搬运。跟手撸 Producer/Consumer 的区别:Connect 不用写代码,配 YAML 就行——Source Connector 从 MySQL、S3、ES 等数据源把数据搬到 Kafka,Sink Connector 从 Kafka 搬到下游。内置容错:Worker 挂了自动转移任务到其他节点,位移管理、重试、转换(Transform)全都现成的。手写 Consumer 得自己管位移提交、Rebalance、错误重试,整一堆重复代码。Connect 适合数据管道类场景——MySQL CDC 到 ClickHouse、日志采集到 HDFS,省掉 90% 的搬运代码,团队只管维护 Connector 插件。适合团队规模不大但又需要频繁接入各种外部系统的情况,一个 Connect 集群能管几十条数据管道。

【面试题】2. 生产者 acks=0、acks=1、acks=all,底层区别是什么?线上为什么推荐 acks=all? ​

【标准答案】acks=0:生产者发完消息不等任何确认,直接返回成功。吞吐最高、延迟最低,但消息可能在网络层就丢了——Broker 还没收到生产者就认为成功了,线上不要用。acks=1:Leader 分区写本地日志成功后就返回确认,不等 Follower 同步。这是"够快但不够安全"的选择——如果 Leader 刚写完还没同步 Follower 就宕机了,新 Leader 没有这条消息,丢了。acks=all(等价 acks=-1):Leader 写完本地日志后,等所有 ISR 副本都同步完才返回确认。性能最低但最安全,只要 ISR 里至少有一个副本存活就不会丢数据。线上推荐 acks=all + min.insync.replicas≥2,这是生产环境消息不丢的底线配置。面试官追问"acks=all 是等所有 AR 还是所有 ISR?"——答案是 ISR,不是所有 ASSIGNED 副本,落后副本不算,这样不会因为一两个慢 Follower 拖死写入。

【面试题】3. Kafka 消费者 subscribe() 和 assign() 两种模式有什么区别?什么场景用 assign? ​

【标准答案】subscribe() 是"加入消费组,让 Kafka 自动分配分区"——你只需指定 Topic,分区分配、Rebalance、故障转移全是 Kafka 自己管。这是生产主流用法,适合水平扩展、高可用场景。assign() 是"你自己指定消费哪些分区"——比如 assign(Arrays.asList(new TopicPartition("order", 0))) 手动绑定分区,脱离消费组机制,Kafka 不帮你管:没有 Rebalance、不保存位移到 __consumer_offsets(除非手动提交)、别的消费者再 assign 同一个分区也不冲突。用 assign 的场景:一、你想精确控制哪个消费者读哪个分区(比如按实例所在机房就近读);二、你要实现自定义的分区分配逻辑,Kafka 自带策略满足不了;三、临时跑一个单机任务从特定分区的第 100 条开始消费。代价是你得自己管故障恢复,消费者挂了不会自动转移分区。绝大多数场景请用 subscribe。

【面试题】4. Kafka Broker 的网络层 Reactor 模型是怎么设计的?一条请求进来经历了什么? ​

【标准答案】Kafka Broker 用 Reactor 多线程模型处理网络请求,核心角色三个:一个 Acceptor 线程负责接收新 TCP 连接,然后轮询分发给多个 Processor 线程;Processor 线程负责从 Socket 读请求数据和写响应数据,干的是纯网络 IO,不碰业务;Processor 把读到的完整请求放入 RequestQueue;接下来 IO 线程池(num.io.threads 控制)从队列里拿请求,解析协议、查日志、读数据,生成响应放入对应 Processor 的 ResponseQueue;Processor 再把响应写回 Socket。这样设计的好处是网络和业务彻底解耦——网络层不阻塞业务处理,业务慢也不影响其他连接的收发。类比:Acceptor 是前台迎宾,Processor 是服务员递菜单和上菜,IO 线程是后厨炒菜。调整关键:num.network.threads 配 CPU 核数,num.io.threads 配 2 倍核数因为涉及磁盘 IO 会阻塞。

【面试题】5. Leader Epoch 是什么?它解决了 Follower 故障恢复时的什么问题? ​

【标准答案】Leader Epoch 是一个单调递增的版本号,每次分区 Leader 换人就 +1,Leader 把当前 Epoch 写到每条消息的 header 里。它解决的是老方案"HW 截断"的致命问题:旧版本 Follower 故障恢复后只能靠 HW 对齐数据,但 HW 取决于所有 ISR 的最小 LEO,当 Follower 全部宕机只有 Leader 存活时,Leader 的 HW 也不推进,Follower 恢复后不知道该截断到哪、可能丢数据也可能多数据。Leader Epoch 的做法是:Follower 恢复时先问 Leader "这个 Epoch 的起始 offset 是多少?",Leader 告诉它,Follower 把超过该 offset 的数据截掉,从 Leader 的对应位置开始同步。这样不管 ISR 里剩几个副本,Follower 都能精确知道从哪截断、从哪追,避免了数据不一致和数据丢失。这是 Kafka 副本一致性的底层基石,大部分面试官不知道这个,你讲出来直接加分。

【面试题】6. Kafka 中延迟操作的"时间轮(TimingWheel)"到底是干什么的?为什么不用 JDK 原生 Timer? ​

【标准答案】Kafka 里大量"等一会儿再执行"的逻辑——比如生产者等 acks、Follower 等 fetch 数据凑够、延迟队列等——全用时间轮实现。时间轮的原理:一个环形数组,每个槽代表一段时间间隔(比如 1ms),一个指针按间隔走,走到哪个槽就执行里面挂的任务。添加任务就是算好延迟后落到哪个槽,O(1) 复杂度。JDK 的 Timer 和 ScheduledThreadPool 底层用堆或优先队列,插入和删除 O(logN),Kafka 这种每秒几十万延迟任务的场景扛不住。时间轮还有一个关键优化:层级时间轮——外层轮精度粗(比如 1 分钟一圈),内层轮精度细(1ms 一圈),像钟表的时针分针秒针组合工作,既支持大延迟(小时级)又支持小延迟(毫秒级)。Kafka 几乎所有超时控制、延时返回都靠它,是实现高吞吐的基础设施。

【面试题】7. 生产者用事务发送,commit 的时候事务协调器突然挂了,消息会丢失吗?恢复机制是什么样的? ​

【标准答案】不会丢。Kafka 事务的容错机制是:事务开始前,生产者发消息到目标分区时,分区 Leader 会记录该分区的"Pending 事务"信息(事务 ID + PID)。同时事务协调器把事务状态写到 __transaction_state 内部 Topic,持久化存储。如果协调器在 commit 过程中挂了,__transaction_state 里的事务记录还在,新选举的协调器读到后发现有"PrepareCommit"或"Ongoing"但没收到最终 Commit 的事务——这时它不会主动 commit,而是等生产者重连后重试 commit。如果生产者不重连且超时(transaction.timeout.ms),协调器会自动 Abort 事务,所有目标分区把 Pending 消息标记为已中止。关键保障点:一、__transaction_state 是 Compact Topic,不丢状态;二、目标分区有 Pending 记录不怕协调器宕机;三、超时兜底防止事务永远悬挂。生产者这边的坑是:transaction.timeout.ms 必须大于你的业务最大处理时间加上 Flink checkpoint 间隔,否则事务中途过期被 abort。

【面试题】8. Kafka Broker 的 JVM 为什么堆内存不能设太大?和生产者的 PageCache 有什么关系? ​

【标准答案】这是一个 Kafka 面试高频题,核心原因:Kafka 靠 OS 的 PageCache(页缓存)来缓存磁盘上的消息日志,而不是堆内存。堆内存主要是存网络缓冲区、元数据、连接对象,这些不大——6G 堆就够绝大多数场景。如果你把堆设得很大(比如 32G),OS 内存大部分被 JVM 吞了,留给 PageCache 的就少了,PageCache 小意味着消费者来读消息大概率穿透磁盘,吞吐暴跌。Kafka 的性能支柱就是"95% 的消费请求命中 PageCache 直接返回,不走磁盘",堆抢了 PageCache 的地盘就是本末倒置。调优建议:堆控制在 6-8G;用 G1GC,-XX:MaxGCPauseMillis=20 控制停顿时间在 20ms 内,-XX:InitiatingHeapOccupancyPercent=35 提前触发并发标记避免 Full GC;堆外内存留给 PageCache,物理机的 70% 以上内存应该给 OS;G1GC 并发标记阶段会扫描所有对象,堆太大会导致标记耗时激增间接 STW。

【面试题】9. 线上某 Broker 频繁报 "CorruptRecordException" 日志损坏,你怎么定位和恢复? ​

【标准答案】日志损坏分两步走:先保业务再修数据。第一步隔离开:立刻停掉这台 Broker,把它从集群摘掉(改 broker.id + 清空 znode 或 KRaft 的注册信息),让 Controller 把它的 Leader 分区切换到其他 Broker,业务恢复。第二步定位范围:用 kafka-dump-log.sh --files /data/kafka-logs/topic-0/00000000000000000000.log --print-data-log 解析损坏分段,看 exception 报在哪个 offset、哪条消息。如果是单条消息损坏:找到该 Segment 的最后正常 offset,用 kafka-delete-records.sh --offset-json-file 从损坏位置往后全部删除(等同截断),Follower 重新从 Leader 同步;如果是整个 Segment 文件系统损坏:直接把该 .log 文件删掉,Broker 启动后检测到缺失会自动从 Leader 重新拉全量——前提是还有健康副本。第三步复盘:查磁盘 smartctl 看有没有坏道;查 Broker 是不是非正常关机(kill -9);检查日志目录是否网络存储(NFS/SMB 容易损坏)。预防:生产环境开启定期 md5sum 校验日志分段。

【面试题】10. Kafka Tiered Storage 分层存储是什么?解决了什么问题?什么场景该上? ​

【标准答案】Tiered Storage 是 Kafka 3.6+ 的重磅特性,核心思路:把冷数据从本地磁盘挪到廉价对象存储(S3/OSS/MinIO),本地只留热数据和索引。传统 Kafka 所有日志数据都存本地磁盘,消息保留多久取决于你买了多大的盘。想保留 30 天的数据?得买 30 天的容量,成本爆炸。分层存储让"计算和存储分离"——Broker 是计算节点只处理读写,历史数据自动归档到对象存储,消费者请求冷数据时 Broker 从远端拉回来返回,对消费者完全透明。适用场景:一、监管要求保留几十天甚至几个月的消息(但只有最近几天的数据被频繁消费);二、批量回溯和数仓场景,延时要求不高但要海量历史数据;三、云原生部署想按需伸缩 Broker 不绑定大量磁盘。不该上的场景:全是热读的低延迟场景(Tiered Storage 读冷数据要跨网络从对象存储拉,延迟大幅增加)。一句话:Tiered Storage 让 Kafka 从"硬盘容量定死"变成"按需用云存储",运维成本和数据灵活性上都是大升级。


生成时间:2026-06-18 22:48 覆盖考点:Kafka核心架构(Kafka Connect)、生产者机制(acks底层区别)、消费者机制(subscribe vs assign)、Broker核心(Reactor网络模型)、ISR同步(Leader Epoch)、消息存储(时间轮)、幂等与事务(事务恢复)、性能调优(JVM+PageCache)、常见故障排查(日志损坏恢复)、高可用设计(Tiered Storage)