Kafka 高性能不是因为“用了内存队列”。恰恰相反,Kafka 的核心数据是写磁盘的。它之所以快,是因为它把磁盘、网络和批处理的效率都用到了极致。
一句话概括:Kafka 快在分区并行、磁盘顺序写、页缓存、零拷贝、批量发送和消息压缩;这些设计共同减少随机 IO、减少用户态和内核态拷贝、减少网络请求次数。
1. 分区:把压力拆开
Kafka 的 Topic 可以拆成多个 Partition。不同分区可以分布在不同 Broker 上,也可以由不同消费者并行消费。
分区带来的好处是:吞吐不再受单台机器、单个文件、单个消费者限制。数据量上来后,可以通过增加分区和 Broker 扩展处理能力。
2. 顺序写:把磁盘用顺
很多人以为写磁盘一定慢,其实随机写慢,顺序写可以很快。
Kafka 的 Partition 本质上是追加日志。新消息不断追加到日志文件末尾,避免了大量随机寻址。
这和数据库频繁修改某一页、某一行不一样。Kafka 大部分写入都是 append-only,所以能充分利用磁盘顺序写能力。
3. 页缓存:把磁盘访问变成内存访问
Kafka 大量依赖操作系统页缓存。写入数据时,数据先进入 Page Cache,再由操作系统异步刷盘;读取热点数据时,也可能直接从 Page Cache 读取。
这样 Kafka 不需要自己维护一套复杂的 JVM 内存缓存,还能减少 JVM GC 压力。操作系统会根据内存情况管理页缓存。
4. 零拷贝:减少数据搬运
传统读取文件再发送到网络,大致会经历多次拷贝:磁盘到内核缓冲区、内核到用户空间、用户空间再回到 Socket 缓冲区,最后发到网卡。
Kafka 使用零拷贝时,可以让数据从页缓存直接进入网络发送路径,减少用户态和内核态之间的数据复制。
它减少的是“无意义搬运”,不是完全没有任何数据移动。面试里说清楚这一点,会比只背“零拷贝”更稳。
更直观地看,传统路径和 sendfile 路径差异如下:
零拷贝依赖操作系统和传输路径。比如开启 SSL/TLS 时,数据需要进入用户空间做加解密,Kafka 的 sendfile 零拷贝路径就会受限。所以它是高性能的重要原因,但不是所有部署形态下都无条件生效。
5. 批量发送:减少网络请求次数
Kafka 生产者不会每来一条消息就立刻发一次网络请求,而是可以把多条消息聚合成批次发送。
批量发送减少了网络往返次数,也让压缩更有效。但批量越大,单条消息等待时间可能越长,所以吞吐和延迟之间要权衡。
6. 消息压缩:减少磁盘和网络 IO
Kafka 支持消息压缩。压缩后的消息体更小,能减少磁盘写入量和网络传输量。
| 优点 | 代价 |
|---|---|
| 降低网络 IO | 消耗 CPU 压缩解压 |
| 降低磁盘 IO | 排查原始消息不如明文直观 |
| 提升批量传输效率 | 小批次压缩收益有限 |
压缩适合消息量大、网络或磁盘 IO 成为瓶颈的场景。
7. 这些设计如何串起来
Kafka 的性能不是某一个点带来的,而是一组设计叠加:
从写入到读取,核心目标都一样:减少随机 IO、减少复制、减少请求次数。
8. 面试回答模板
可以这样答:
Kafka 高性能主要来自几个设计。第一,Topic 可以拆成多个分区,分区分布在不同 Broker 上,生产和消费都可以并行。第二,Kafka 的 Partition 是追加日志,写入是顺序写,磁盘顺序写性能很高。第三,Kafka 充分利用操作系统 Page Cache,写入先进入页缓存,读取热点数据也可以直接从页缓存走,减少磁盘访问和 JVM 缓存压力。第四,Kafka 使用 sendfile 这类零拷贝能力,读取数据发送给消费者时减少内核态和用户态之间的数据拷贝;但如果开启 SSL/TLS,零拷贝路径会受限。第五,生产者支持批量发送和消息压缩,减少网络请求次数、磁盘 IO 和网络 IO。所以 Kafka 快不是因为不落盘,而是因为它用顺序写、页缓存和零拷贝把磁盘和网络效率用得很高。
9. 小结
Kafka 为什么快,可以压缩成一句话:
不要只说“Kafka 用了零拷贝”。零拷贝只是其中一环,真正的高吞吐来自整条数据路径都在减少浪费。