一、前言:为什么需要 Nginx 本地缓存?
你是否面临这些痛点?
- ❌ 后端服务压力大,大量重复请求打到应用层
- ❌ 静态资源(图片、JS、CSS)频繁回源
- ❌ 接口响应慢,用户体验差
- ❌ 后端宕机时,整个服务不可用
Nginx 本地缓存(proxy_cache) 是官方提供的服务端缓存机制 ,它能:
✅ 将后端响应缓存到本地磁盘或内存
✅ 相同请求直接返回缓存,绕过后端
✅ 实现"缓存托底"------后端挂了也能返回旧数据
本文将带你从零配置 proxy_cache,并提供生产级最佳实践。
二、核心原理:proxy_cache 如何工作?

💡 关键点:
- 缓存存储在本地磁盘(可配置内存)
- 缓存键(key)默认基于
$scheme$proxy_host$request_uri- 支持按状态码、Header 控制是否缓存
三、基础配置:5 步开启 Nginx 缓存
步骤 1:定义缓存区域(http 块)
Lua
http {
# 定义缓存路径和参数
proxy_cache_path /var/cache/nginx
levels=1:2 # 目录层级(防单目录文件过多)
keys_zone=my_cache:100m # 共享内存区名:大小(存放 key 和元数据)
inactive=60m # 60分钟未访问则删除
max_size=10g # 磁盘最大缓存大小
use_temp_path=off; # 直接写入缓存目录,避免临时文件拷贝
# 创建缓存目录并授权
# mkdir -p /var/cache/nginx && chown -R nginx:nginx /var/cache/nginx
}
🔍 参数详解:
levels=1:2:生成两级子目录(如/a/bc/abcdef...),避免单目录 inode 耗尽keys_zone:1MB 内存约可存 8000 个 keyuse_temp_path=off:必须关闭,否则性能下降 30%+
步骤 2:在 server/location 启用缓存
Lua
server {
listen 80;
server_name api.example.com;
location / {
# 启用缓存,使用名为 my_cache 的区域
proxy_cache my_cache;
# 设置缓存 key(可自定义)
proxy_cache_key "$host$request_uri";
# 哪些状态码响应可以被缓存
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_valid any 5m;
# 透传 Host 和真实 IP
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://backend;
}
}
步骤 3:定义上游服务
Lua
upstream backend {
server 10.0.0.10:8080;
server 10.0.0.11:8080;
}
四、高级配置:精准控制缓存行为
4.1 自定义缓存 Key
Lua
# 按用户 ID + URL 缓存(个性化内容)
proxy_cache_key "$host|$request_uri|$cookie_user_id";
# 忽略查询参数中的 token(避免缓存爆炸)
proxy_cache_key "$host|$uri";
4.2 缓存状态透传(用于监控)
Lua
# 添加缓存状态头
add_header X-Cache-Status $upstream_cache_status;
# 可能的值:
# - MISS:未命中
# - HIT:命中
# - EXPIRED:过期(正在更新)
# - BYPASS:强制跳过缓存
4.3 强制跳过缓存(调试用)
Lua
# 请求带 nocache=1 时不走缓存
if ($arg_nocache = "1") {
set $nocache "1";
}
proxy_cache_bypass $nocache;
proxy_no_cache $nocache;
五、生产级最佳实践
5.1 缓存托底(后端宕机时返回旧数据)
Lua
location /api/ {
proxy_cache my_cache;
proxy_cache_valid 200 5m;
# 即使后端返回 5xx,也允许使用过期缓存
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
# 后端挂了?直接返回 stale(过期但可用)缓存
proxy_cache_background_update on; # 后台更新缓存
proxy_pass http://backend;
}
✅ 效果:
- 后端宕机 → 用户仍能看到最近一次有效数据
- 服务 SLA 从 99% 提升至 99.99%
5.2 性能优化建议
| 项目 | 推荐值 | 说明 |
|---|---|---|
| 缓存目录 | SSD 磁盘 | 避免 HDD I/O 瓶颈 |
| keys_zone | 100~500MB | 根据 QPS 调整 |
| max_size | ≤ 磁盘 80% | 防止占满磁盘 |
| inactive | ≥ 业务更新周期 | 避免频繁重建 |
5.3 清理缓存(Purging)
Nginx 开源版不支持 PURGE,可通过删除文件 + reload实现:
bash
# 删除特定 URL 缓存(需知道 key 的哈希值)
rm -f /var/cache/nginx/a/bc/abcdef123456...
# 或清空整个缓存
rm -rf /var/cache/nginx/*
nginx -s reload
💡 企业方案 :使用 Nginx Plus 的
proxy_cache_purge指令。
六、验证与监控
6.1 检查缓存是否生效
bash
curl -I http://api.example.com/user/profile
# 查看响应头
# X-Cache-Status: HIT
6.2 监控缓存指标
bash
# 查看缓存目录大小
du -sh /var/cache/nginx
# 统计缓存文件数
find /var/cache/nginx -type f | wc -l
# 日志记录缓存状态(access_log)
log_format cache '$remote_addr - $upstream_cache_status [$time_local] '
'"$request" $status $body_bytes_sent';
access_log /var/log/nginx/cache.log cache;
七、常见问题排查
| 问题 | 原因 | 解决 |
|---|---|---|
| 缓存未生效 | 后端返回 Cache-Control: no-cache |
用 proxy_ignore_headers Cache-Control; 忽略 |
| 磁盘写满 | max_size 未设置 |
设置合理的 max_size |
| 缓存穿透 | 大量唯一 URL(如带时间戳) | 规范 URL,或用 proxy_cache_key 去重 |
| 中文乱码 | 编码不一致 | 确保后端返回 UTF-8 |
八、结语
感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!