主要内容:

  • 介绍 Page Cache
  • 介绍 Kafka Page Cache 的思想

1、什么是 Page Cache ?

CPU 要想访问外存(磁盘)文件,就需要先将磁盘文件数据 Copy 到内存中。而磁盘的访问和传输速度相比于内存慢了几个数量级。操作系统将用来缓存数据的空闲内存就叫做 Page Cache。应用程序产生 Page Cache 的逻辑示意图如下。很明显,Page Cache 是内核管理的内存,也就是说,它属于内核态不属于用户态。

用户进程启动 read() 系统调用后,内核会首先查看 Page Cache 里有没有用户要读取的文件内容,如果有(Cache Hit),那就直接读取,没有的话(Cache Miss)再启动 I/O 操作从磁盘上读取,然后放到 Page Cache 中,下次再访问这部分内容的时候,就可以直接从 Page Cache 中取了。

2、Kafka PageCache 思想

Kafka 重度依赖底层操作系统提供的 Page Cache 功能,借力于 Linux 内核的 Page Cache,不(显式)用内存,胜用内存。当写操作发生时,它只是将数据写入 Page Cache 中,并将该页置上 Dirty 标志。当读操作发生时,它会首先在 Page Cache 中查找内容,如果有就直接返回了,没有的话就会从磁盘读取文件再写回 Page Cache。实际上 Page Cache 是把尽可能多的空闲内存都当做了磁盘缓存来使用。同时如果有其他进程申请内存,回收 Page Cache 的代价又很小,所以现代的 OS 都支持 Page Cache。

  • Kafka 在运行过程中,会尽可能多的把空闲内存都当做了磁盘缓存来使用。
  • 如果 Kafka Producer 的生产速率与 Consumer 的消费速率相差不大,那么就能几乎只靠对 Broker Page Cache 的读写就可以完成整个生产-消费过程,所有的数据都在内存中。这是 Kafka 的高吞吐量的保证。
  • Kafka 使用 Page Cache 功能同时可以避免在 JVM 内部缓存数据。
    • 如果在 Heap 内管理缓存,JVM 的 GC 线程会频繁扫描 Heap 空间,带来不必要的开销,
    • JVM 对象头会带来很多空间浪费,内存的有效空间利用率会因此降低。
  • Kafka 重启后,OS 管理的 Page Cache 不会被释放,依然可以继续使用。
  • Kafka 的刷盘机制,会将 Page Cache 中 的消息数据刷到磁盘当中,保证数据不会丢失。

曾经,我碰到过一个线上环境的问题:该集群上 Consumer 程序一直表现良好,但是某一天,它的性能突然下降,表现为吞吐量显著降低。我在查看磁盘读 I/O 使用率时,发现其明显上升,但之前该 Consumer Lag 很低,消息读取应该都能直接命中页缓存。此时磁盘读突然飙升,我就怀疑有其他程序写入了页缓存。后来经过排查,我发现果然有一个测试 Console Consumer 程序启动,“污染”了部分页缓存,导致主业务 Consumer 读取消息不得不走物理磁盘,因此吞吐量下降。找到了真实原因,解决起来就简单多了。

相关阅读:

  1. Kafka-Pagecache原理
  2. 聊聊page cache与Kafka之间的事儿
  3. 38 调优Kafka,你做到了吗?