根本问题在于缓存写入路径与磁盘能力不匹配;需禁用 use_temp_path、扁平化目录结构、增大 keys_zone、将缓存置于高性能 nvme 或 tmpfs,并关闭 directio、启用 sendfile 及 worker 绑核。

根本问题不在缓存本身,而在缓存写入路径与磁盘能力不匹配。Nginx 的 proxy_cache 或静态文件服务一旦开启,高频小文件缓存写入会迅速暴露底层存储的随机 I/O 瓶颈——尤其当缓存目录落在普通 SSD、HDD 或共享存储上时,Worker 进程会在 write() 或 rename() 系统调用处阻塞,表现为 CPU 利用率不高但请求延迟飙升、iostat 中 %util 接近 100%、iotop 显示 worker 进程持续处于 D(不可中断睡眠)状态。
关闭 use_temp_path,消除双倍落盘和跨设备失败
默认情况下,Nginx 先将响应体写入临时目录(如 /var/lib/nginx/proxy_temp),再 rename() 到缓存目录。这不仅是两次磁盘写入,更在临时目录与缓存目录挂载点不同时直接失败(返回 502),或因 rename 跨设备而退化为 copy+unlink,加剧 I/O 压力。
- 显式禁用:在
proxy_cache_path中添加use_temp_path=off - 同步清理冗余配置:删掉独立的
proxy_temp_path指令,它已失效 - 确保缓存目录所在分区有足够空间(建议预留 ≥20%),所有写入直落目标路径
扁平化缓存目录结构 + 加大 keys_zone
多级 hash 目录(如 levels=1:2:2)在高并发下引发海量 inode 查找和路径遍历,把本可顺序写的操作变成随机读+写,对 HDD 和部分 NVMe 都是重压。
- 改用浅层结构:
levels=2(最多 256 个一级子目录),避免深度嵌套 - 扩大元数据缓存:
keys_zone=mycache:256m(非 64m 或 128m),减少 key 查询穿透磁盘 - 若用 XFS 文件系统,挂载时加
noatime,inode64,logbufs=8,logbsize=256k
把缓存物理位置“提”到更快层级
磁盘 I/O 卡顿本质是介质跟不上请求节奏。与其调参数,不如换路径:
- 开发/压测环境:直接挂载到
/dev/shm(tmpfs):proxy_cache_path /dev/shm/nginx_cache levels=2 keys_zone=mycache:128m max_size=8g use_temp_path=off;
需同步调大内核参数:vm.shmmax = 8589934592、vm.shmall = 2097152 - 生产环境:缓存目录必须独占一块高性能 NVMe 盘,且与系统日志、数据库等 I/O 重负载隔离
- 严禁使用 NFS、APFS 加密卷、Docker overlay 默认卷——它们不保证原子写入,极易触发重试和卡顿
协同内核与 Nginx 减少写放大
即使换了硬件,不当配置仍会让 I/O 效率打折:
- 关闭
directio(保持默认或显式directio off):小缓存文件走 page cache 才能被预读和合并,directio反而绕过优化 - 确认
sendfile on已启用:对缓存命中响应,内核可零拷贝发送,避免 read+write 多次系统调用 - Worker 绑核:
worker_processes auto;+worker_cpu_affinity auto;(Nginx ≥ 1.19.10),防止跨核迁移导致 L1/L2 缓存失效,拖慢 page cache 查找











