Linux

PageCache 原理

·7 分钟阅读·2506 字
📋 目录

PageCache 原理

核心概念 PageCache(页高速缓存)是 Linux 内核在内存中开辟的文件系统缓存,以 Page 页为最小单位(默认 4KB),用于缓存磁盘文件数据。所有普通文件读写、Kafka 日志读写都会经过 PageCache,应用程序无法直接操作磁盘。

1. 基础概念

1.1. 什么是 PageCache

PageCache 是 Linux 内核的页高速缓存,位于内存和磁盘之间的一层缓存层。当应用程序读写文件时,数据先经过 PageCache,再由内核异步刷入磁盘。

核心特性:

  • 最小单位:Page 页(默认 4KB)
  • 缓存对象:磁盘文件数据块
  • 透明性:应用程序无感知,内核自动管理
  • 适用范围:所有普通文件 IO(read/write/mmap)

1.2. 两种 IO 模式对比

模式数据路径拷贝次数适用场景
标准读写(read/write)用户缓冲区 PageCache 磁盘2 次拷贝通用文件 IO
mmap 内存映射直接映射到进程虚拟地址空间0 次额外拷贝Kafka 索引文件、大文件随机访问

mmap 将磁盘文件直接映射到进程虚拟地址空间,进程读写内存等价于读写 PageCache,省去了用户态到内核态的数据拷贝。

2. 写入逻辑与刷盘机制

2.1. 写入流程

应用程序 write()

PageCache(标记为脏页 Dirty Page)

pdflush / writeback 内核线程(异步)

磁盘
  • 写回延迟:write() 写入 PageCache 后立即返回,数据以脏页形式暂存在内存
  • 写回策略:内核不立即刷盘,而是积累到一定条件再批量写入磁盘(合并多次小 IO 为一次大 IO)

2.2. 刷盘触发条件

触发条件参数默认值说明
脏页比例超阈值vm.dirty_ratio20%脏页占内存比例超过此值,进程阻塞并同步刷盘
脏页绝对阈值vm.dirty_background_ratio10%后台线程开始异步刷盘
脏页超时vm.dirty_expire_centisecs3000(30秒)脏页停留超过此时间强制刷盘
内存压力--系统内存不足时回收 PageCache

3. 读写流程

3.1. 读操作

磁盘 → PageCache → 用户缓冲区

场景 A:PageCache 命中
  ✅ 直接返回,无磁盘 IO(纳秒级延迟)

场景 B:PageCache 未命中
  ❌ 发起磁盘 IO 读取到 PageCache(毫秒级),再拷贝到用户缓冲区

3.2. 写操作

用户缓冲区 → PageCache(标记脏页)→ 磁盘

1. 数据从用户缓冲区拷贝到 PageCache
2. 该页标记为脏页(Dirty Page)
3. write() 立即返回(毫秒级)
4. 内核异步通过 pdflush/writeback 线程刷盘(后台执行)

3.3. 性能关键点

  • 读命中率是核心指标 — 命中率高则 IO 性能接近内存
  • 脏页比例控制写延迟 — 比例过高会导致写 IO 卡顿
  • 顺序 IO 利用预读(readahead)机制,提前将后续数据加载到 PageCache

4. Kafka 对 PageCache 的依赖

Kafka 是高吞吐消息队列,其性能高度依赖 PageCache 机制:

4.1. 顺序写与 PageCache

  • Kafka 消息追加到 segment 文件末尾(顺序写),磁盘顺序写性能接近内存
  • 新写入的数据缓存到 PageCache,消费者读取最新消息时几乎全部命中 PageCache
  • 无需磁盘 IO,实现读写分离:写线程刷盘,读线程从 PageCache 直接取

4.2. mmap 索引文件

  • .index 和 .timeindex 索引文件使用 mmap 映射到 PageCache
  • 索引查找时直接读取内存,避免索引文件的磁盘 IO

4.3. Kafka 最佳实践

Kafka 调优建议

  • 给 Kafka 预留足够内存(PageCache 越大,读缓存命中率越高)
  • 不要在同一台机器运行其他占用 PageCache 的应用(竞争缓存)
  • 监控 dirty_ratio 和 dirty_background_ratio,避免刷盘风暴

5. PageCache 与零拷贝

零拷贝技术 sendfile/splice 等零拷贝技术允许数据在 PageCache 和网卡之间直接传输,不需要经过用户缓冲区。Kafka 利用 sendfile 实现消费端数据直接从 PageCache Socket,实现高吞吐网络传输。

6. 监控与调优

6.1. 查看 PageCache 使用量

# 查看内存详情(cached 列)
free -h

# 查看详细 PageCache 统计
cat /proc/meminfo | grep -E "^(Cached|Dirty|Writeback|PageTables)"

# 查看脏页比例
sysctl vm.dirty_ratio vm.dirty_background_ratio

6.2. 常见排查场景

场景现象排查方向
PageCache 占用过高free 中 cached 持续增长检查是否有大量文件 IO 应用,考虑 drop_caches
写 IO 突然飙高iostat 写吞吐暴涨检查 dirty_ratio 是否触发刷盘阈值
读缓存命中率低应用响应慢、磁盘读 IO 高检查内存是否不足导致 PageCache 被回收

关联文档