Page Cache 是 Linux 内核中文件 I/O 的一级、默认、必经缓存层;Nginx 静态服务时依赖其加速读取,与 open_file_cache 协同提升元数据访问效率,并可与 proxy_cache 等机制分层协作,而非作为其二级缓存。

Page Cache 本身不是“二级缓存”,它是 Linux 内核中文件 I/O 的**一级、默认、必经缓存层**。所谓“配合 Nginx 提升二级文件缓存”,实际指的是:在 Nginx 静态服务场景下,**合理利用 Page Cache 的天然加速能力,同时避免其副作用,并与 Nginx 自身的缓存机制(如 proxy_cache 或磁盘静态缓存)形成协同,而非冲突**。
理解 Page Cache 在 Nginx 场景中的真实角色
当 Nginx 用 root 或 alias 直接提供静态文件时(非 proxy_pass),它最终调用的是内核的 read() 系统调用。此时:
- 若文件已在内存中被 Page Cache 缓存,Nginx 几乎零延迟读取——这是最理想状态;
- 若未缓存,内核会从磁盘加载数据进 Page Cache,再返回给 Nginx,后续请求即可命中;
- Page Cache 是全局共享的,多个 Nginx worker 进程访问同一文件,只占用一份内存副本;
- 它对顺序大文件(如视频、安装包)效果极佳,预读(readahead)可大幅减少实际磁盘 IO 次数。
让 Page Cache 稳定高效服务 Nginx 的关键操作
Page Cache 不需要“开启”,但需要“善待”。重点是防止它被干扰或失效:
-
禁用
sendfile on对小文件无益,但对大文件慎用:虽然sendfile能减少内核态到用户态拷贝,但它依赖 Page Cache。若系统内存紧张、Page Cache 被大量回收,sendfile可能退化为低效路径。对高并发大文件分发,建议结合directio(见后文); -
启用
open_file_cache:它缓存的是文件句柄、inode 和元数据(如大小、修改时间),不占 Page Cache 内存,却能极大减少stat()和open()系统调用开销,让 Page Cache 更专注数据本身; -
避免频繁写入同一文件:写入会触发脏页回写和锁竞争,干扰读取性能。日志类文件应分离存储,静态资源目录设为只读挂载(
mount -o remount,ro); -
适度调优
/proc/sys/vm/vfs_cache_pressure:默认值 100 可能导致 dentry/inode 缓存过早回收,间接影响 Page Cache 命中率;设为 50–80 可增强文件系统缓存稳定性。
与 Nginx “二级缓存”机制的正确配合方式
这里“二级”通常指 Nginx 自己管理的缓存,不是 Page Cache 的下级,而是不同层级的协作:
-
静态文件直出 + Page Cache = “一级加速”:适用于 CSS/JS/图片等高频、稳定资源。配置
expires max和强缓存头,让浏览器长期复用,Nginx 层只需极轻量地校验文件是否存在(靠open_file_cache加速),数据直接从 Page Cache 返回; -
proxy_cache = “二级代理缓存”:适用于反向代理后端(如 PHP、API)。它缓存的是 HTTP 响应体(含响应头),与 Page Cache 完全无关。此时应关闭
sendfile和gzip(避免压缩干扰缓存哈希),并确保后端返回正确Cache-Control; -
Laravel Page Cache 等磁盘静态缓存 = “零级预生成”:这类工具把动态响应提前生成为 HTML 文件,Nginx 用
try_files直接当作静态文件服务——它完美落入 Page Cache 加速路径,是最高效的组合之一。
何时该绕过 Page Cache?—— directio 的适用边界
Page Cache 并非万能。当服务 GB 级单一文件(如 ISO、4K 视频)且并发下载量大时,Page Cache 反成负担:
- 整块加载吃光内存,引发 OOM 或 kswapd 抖动;
- 多个连接争抢同一缓存页,产生锁竞争;
- 冷数据反复换入换出,实际磁盘读反而更慢。
此时启用 directio 1m(需满足:location 用 root/alias、文件 ≥1MB、ext4/xfs、sendfile off、gzip off、补全 Content-Length)可绕过 Page Cache,由 Nginx 直接发起 O_DIRECT 读,实现内存可控、延迟稳定、CPU 下降。











