缓存命中率低主因是url中无意义参数导致key分裂,需通过map清洗query、忽略静态资源参数、谨慎处理cookie/header、统一编码大小写,并用x-cache-key或日志验证key收敛效果。

缓存命中率低,常常不是因为没开缓存,而是请求被“悄悄拆散”了——同一个资源,因 URL 中混入无意义参数(如 utm_source、t=1727736380、_v=abc123),导致 Nginx 生成大量重复缓存条目。优化缓存键(proxy_cache_key)的核心,是让语义相同的请求收敛到同一个 key,同时排除干扰项。
剥离无意义 query 参数
默认的 $request_uri 包含完整 query string,哪怕只差一个跟踪参数,key 就完全不同。必须提前清洗:
- 用
map指令提取有效参数,丢弃干扰项。例如只保留id、lang、version,其余全过滤:
default "";
"~*id=([^&]+)&lang=([^&]+)" "$1|$2";
"~*id=([^&]+)" "$1";
}
proxy_cache_key "$scheme$host$uri?$clean_args";
- 对纯静态资源(js/css/img),直接忽略所有 query:
proxy_cache_key "$uri";,再配合proxy_ignore_headers Cache-Control;防后端干扰
谨慎处理 Cookie 和 Header
除非业务强依赖用户身份(如会员专享页),否则不要把 $cookie_xxx 或 $http_user_agent 直接写进 key:
- 含登录态的页面,可用
Vary: Cookie+proxy_cache_key "$scheme$host$request_uri $cookie_session_id",但要确保 session ID 稳定且不泄露隐私 - 区分灰度或地域的接口,建议让后端返回稳定标识(如
X-Region: sh),再用map $upstream_http_x_region $region_key提取,比依赖客户端 header 更可靠
统一大小写与编码格式
有些客户端会把 %20 和空格混用,或大小写不一致(/API/USER vs /api/user),导致 key 分裂:
- 用
underscores_in_headers on;并统一转小写(需配合 Lua 或 OpenResty);更简单做法:在 location 中强制标准化 URI - 静态资源可加
location ~* \.(js|css|png|jpg|gif)$ { rewrite ^(.*)$ $1 permanent; },再配proxy_cache_key "$scheme$host$uri"; - 对大小写敏感路径,用
map转小写(Nginx 1.19+ 支持$uri_lowercase)
验证 key 是否真正收敛
别只看配置,要实测是否生效:
- 开启
add_header X-Cache-Key $cache_key;(需编译时启用--with-http_realip_module等支持)或用日志记录:log_format cache_log "... $cache_key"; - 抓几组相似请求(带/不带 utm、不同时间戳),对比响应头中的
X-Cache-Key是否一致 - 查日志:
awk '{print $13}' access.log | sort | uniq -c | sort -nr | head -5,看高频 key 是否集中在预期模式上











