面试记录 2026-09-22
题目:Kafka 为什么这么快?
难度:medium
标签:db/mq/kafka, mq/kafka, general/knowledge, difficulty/medium
评分:⭐⭐☆☆☆(2/5)
我的回答
Kafka 快的原因,我理解是核心主要是两个,一个是通过分片,多分片去进行数据写入。第二个是它对缓存数据的写入使用磁盘顺序写,更大的压榨了磁盘的性能。然后通过分区分片保证了提升了并发的性能。然后实现导致的它的速度会更快。
点评
优点:
- 抓到了两个关键点:分区并行和顺序磁盘写——这是 Kafka 高吞吐最核心的两条腿
不足:
- 只答了 2/8,遗漏太多关键机制
- 完全没提到 零拷贝(sendfile)——这是 Kafka 消费端性能的最重要亮点
- 没提到 Page Cache、批量+压缩、长轮询、索引结构(Hash/Time Index)
- "缓存数据的写入"表述含糊,Kafka 是磁盘追加写 + OS Page Cache,不是内存缓存
补充(本题的完整答案框架):
- 顺序磁盘 I/O:分区日志追加写入,磁盘顺序写接近内存速度
- 零拷贝(sendfile/mmap):消费端从磁盘直接到网卡,绕过用户态拷贝和 CPU
- Page Cache:所有读写走 OS 页缓存,减少系统调用
- 分区并行:多分区分布在多 Broker 上并行读写
- 批量 + 压缩:Producer 攒批、Broker 按 batch 存储和压缩传输
- 长轮询:无消息时挂起连接,避免空轮询
- 索引优化:Hash Index + Time Index,O(log n) 定位
- 异步复制(ISR):Leader 写本地即返回
完整讲解
第一部分:知识重点剖析
核心考点定位:考察对 Kafka 高吞吐底层机制的系统理解——不是某一个点,而是多个层次(存储、网络、调度、副本)协同的结果。
知识点拆解:
- 存储层:顺序写 + 页缓存 + 索引
- 每个 Partition 是一个 append-only 的日志文件,写入永远是追加,磁盘顺序写性能可达 600MB/s+
- 所有读写先经过 OS Page Cache,热数据全在内存
- 每个 segment 文件配两个索引:
.index(Hash Index,offset→物理位置)和 .timeindex(时间戳索引),查找都是二分 O(log n)
- 网络层:零拷贝
- 消费者读取消息时,Broker 用 mmap + sendfile 组合:把文件页 mmap 到内核态,sendfile 直接把页拷贝到网卡,数据不进入用户态
- 相比传统 read→write 需要 4 次拷贝(磁盘→内核→用户→内核→网卡),零拷贝只需 2 次(磁盘→内核→网卡)
- 调度层:批量 + 压缩 + 长轮询
- Producer
batch.num.messages + linger.ms 攒批,一次请求发一批
- Broker 支持 gzip/snappy/lz4/zstd 压缩传输,压缩粒度是 batch
- Consumer
poll() 无消息时挂起连接(默认 5s),服务端有消息才唤醒,避免 5s 一次空轮询
- 副本层:异步复制
- Leader 收到消息写本地即返回 ack(ack=1),ISR 副本异步追
- ack=all 才要求所有 ISR 副本都确认
- 协议层:二进制协议 + 多路复用
- Kafka 协议是二进制、紧凑、无 RPC 框架开销
- 单连接上多 Partition 请求复用,减少连接数
8 个层次叠加,才能让 Kafka 单机轻松打出 10万+ QPS。
第二部分:考察方向与延伸递进
考察方向:
- 深度:零拷贝的实现细节(mmap vs sendfile、DirectBuffer)、Page Cache 淘汰策略、压缩对 CPU 的代价
- 广度:与 RocketMQ 的零拷贝实现对比(CommitLog 全量顺序写 vs Kafka 分区独立写)、与 Elasticsearch 的 Lucene 索引对比
- 应用:如何权衡压缩率和 CPU、如何评估 Page Cache 命中率、如何做 Producer 端参数调优
延伸递进面试题:
- 零拷贝的 sendfile 和 mmap 组合,为什么比单独的 sendfile 更好?
- 解答要点:sendfile 本身有 checksum CRC 的 CPU 开销,Kafka 用 mmap 让 CRC 校验在 mmap 时同步完成,避免二次拷贝
- Kafka 为什么选择磁盘而不是内存存储?
- 解答要点:Page Cache 让热数据全在内存,磁盘只是兜底;内存存储成本高、无法持久化;磁盘顺序写足够快
- Producer 的
linger.ms 和 batch.size 怎么权衡?
- 解答要点:linger.ms 越大,攒批效果越好,但延迟越高;批量压缩率随 batch 增大而提升;生产上一般 5-50ms
第三部分:面试者参考回答(300-600 字口语化)
面试官您好,Kafka 快不是靠某一个点,而是多个层次的机制协同。
第一个是顺序磁盘 I/O。每个 Partition 是一个 append-only 的日志文件,写盘永远是追加写,磁盘顺序写的性能可以接近内存,能达到 600MB/s 以上,而随机写会慢几个数量级。
第二个是零拷贝,这是消费端的关键。Broker 用 mmap + sendfile 的组合,把消息从磁盘直接拷贝到网卡,数据不经过用户态,传统 read-write 要 4 次拷贝,零拷贝只需 2 次,CPU 和带宽开销大幅降低。
第三个是Page Cache。所有读写先经过 OS 页缓存,热数据天然在内存里,磁盘只是兜底持久化,所以 Kafka 才敢用磁盘而不是内存存储。
第四个是分区并行。多分区分布在多 Broker 上,写入和读取都是并行的,横向扩展线性增长。
第五个是批量和压缩。Producer 端通过 linger.ms 和 batch.size 攒批,Broker 按批次压缩传输,压缩率和吞吐都提升。
第六个是长轮询。消费者无消息时挂起连接,避免 5 秒一次的空轮询,网络开销大幅降低。
再往上还有索引优化(Hash Index + Time Index,O(log n) 定位)、异步复制(Leader 写本地即返回)、二进制协议多路复用等,加起来才能做到单机 10万+ QPS。
生产上常见的坑是压缩率的选择:lz4 兼顾速度和压缩率,zstd 压缩率更高但 CPU 消耗更大,需要根据业务量级权衡。