很多人第一次配 Nginx 缓存,容易被 proxy_cache_path、proxy_cache_key、proxy_cache_valid 这一串指令劝退。其实它并不复杂,核心就是先定义缓存放哪、怎么命名、哪些请求能缓存、命中后缓存多久,再决定什么时候绕过缓存或重新验证。
下面先放一份完整示例,再按实际使用时最关心的几个问题拆开说明。看完之后,你可以更快判断一套缓存配置到底是在提升命中率,还是在制造磁盘、权限和过期策略上的隐患。
先看一份可用的 Nginx 缓存配置
http {
# 缓存路径
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m use_temp_path=off;
server {
listen 80;
server_name example.com;
location / {
# 启用缓存
proxy_cache my_cache;
proxy_pass http://backend_server;
# 缓存控制头
add_header X-Proxy-Cache $upstream_cache_status;
# 缓存有效期
expires 30d;
# 缓存方法
proxy_cache_methods GET HEAD;
# 缓存键
proxy_cache_key "$scheme$proxy_host$request_uri";
# 缓存条件
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
# 缓存刷新
proxy_cache_bypass $http_pragma;
proxy_cache_revalidate on;
}
}
}
这份配置分成两层:http 块负责定义缓存区本身,location 块负责决定请求怎样使用这块缓存。理解这两个层级,后面的参数就好拆了。
缓存目录和缓存区参数怎么理解
proxy_cache_path 是整套配置的基础
proxy_cache_path 用来定义缓存的物理存储位置,以及缓存区的几个核心约束条件:

proxy_cache_path /var/cache/nginx:指定缓存文件保存路径。levels=1:2:定义缓存目录层级,例如/var/cache/nginx/c/29/...,这样可以避免单个目录下堆太多文件。keys_zone=my_cache:10m:定义缓存区域名称和元数据内存大小。这里的my_cache是后面proxy_cache要引用的名字,10m通常足够存几万个键。max_size=1g:限制缓存最大磁盘占用,超过1g后 Nginx 会自动清理旧缓存。inactive=60m:缓存项如果在60m内没有被访问,会被视为不活跃并清理。use_temp_path=off:通常建议关闭,直接写入缓存目录,减少额外 I/O 开销。
这一段主要解决的是“缓存存哪里、能占多大、多久不用会被清掉”三个问题。它决定了缓存区的磁盘行为,也直接影响线上空间占用和写入效率。
请求进入后,缓存是怎么生效的
proxy_cache 和 proxy_pass 分别负责什么
proxy_cache my_cache;:启用缓存,并指定使用前面定义的my_cache区域。proxy_pass http://backend_server;:指定后端服务地址,缓存内容就是从这个后端响应里来的。
哪些请求适合缓存
proxy_cache_methods GET HEAD; 表示只缓存 GET 和 HEAD 请求。这个设置比较常见,因为 POST 这类请求通常带有提交、变更或用户态语义,默认不适合直接缓存。

缓存键为什么重要
proxy_cache_key "$scheme$proxy_host$request_uri"; 用来定义缓存键生成规则。这里用的是协议 + 域名 + 路径和参数,也就是按完整请求地址来区分缓存对象。
缓存键的本质是“如何判断两次请求是不是同一个资源”。如果这里定义得过粗,可能把不该共用的响应混到一起;如果定义得过细,又会让命中率下降。
缓存时长、命中状态和浏览器缓存如何配合
proxy_cache_valid 决定后端响应缓存多久
proxy_cache_valid 可以按 HTTP 状态码分别设置缓存时间:
proxy_cache_valid 200 302 10m;:把200和302响应缓存10m。proxy_cache_valid 404 1m;:把404响应缓存1m,避免某些不存在资源被反复请求时持续打到后端。
这里的核心思路是:常见成功响应可以适当放长,错误响应通常设短一些,既减压又避免错误状态长期滞留。
expires 30d 管的是浏览器端缓存
expires 30d; 影响的是客户端浏览器缓存策略,表示资源在浏览器侧可缓存 30d。它和 proxy_cache_valid 不是一回事:前者偏向用户侧,后者偏向 Nginx 到后端这一层。
如何判断这次请求是否命中缓存
add_header X-Proxy-Cache $upstream_cache_status; 会在响应头里加入缓存状态,常见值如 HIT、MISS。调试时,这个头非常实用,可以快速确认缓存有没有真正工作起来。
什么时候绕过缓存,什么时候重新验证
客户端要求不走缓存时怎么办
proxy_cache_bypass $http_pragma; 表示如果请求头里带有 Pragma: no-cache,就绕过当前缓存,直接回源到后端。这类配置常用于调试、强制刷新,或者某些业务场景下需要主动跳过缓存。
缓存过期后不一定要完整重下
proxy_cache_revalidate on; 用来启用缓存重验证。当缓存对象过期后,如果后端资源实际没有变化,Nginx 可以通过重新验证减少不必要的数据传输,降低带宽消耗。
这一步的价值在于,它不是简单地“过期就重拉整个响应”,而是尽量利用协议层验证机制,把回源成本控制得更低。
上线前最容易踩的几个坑
- 确认 Nginx 进程对缓存目录有写入权限,否则服务启动后很容易持续报错。
- 缓存大小和缓存时长不要照抄示例。静态资源一般可以设置得更长,动态页面通常更适合短缓存,必要时结合
proxy_cache_bypass做主动刷新。 - 生产环境建议启用 HTTPS,避免缓存内容在传输过程中泄露敏感信息;同时也要注意缓存目录本身的权限隔离。
Nginx 缓存配置真正难的地方,不是指令多,而是每个参数都在对应一个具体取舍:命中率、磁盘占用、回源频率、调试便利性和安全边界。把这些关系想清楚,再按业务类型微调,整套策略就会顺很多。









