缓存键优化核心是让语义一致请求生成相同key、排除不改变响应的干扰变量:过滤UTM等无意义参数,按终端、地域等业务维度精准分层,避免Cookie等导致缓存分裂,并通过日志分析验证效果。

缓存键(proxy_cache_key)是决定“相同请求是否命中同一缓存条目”的核心。键设计太宽泛,会把不同内容混为一谈;太琐碎,又导致重复缓存、空间浪费、命中率下降。优化关键在于:**让语义一致的请求生成完全相同的 key,同时排除所有不改变响应内容的干扰变量。**
过滤无意义的 URL 参数
UTM 跟踪参数(utm_source、utm_medium)、AB 测试 ID、设备标识符(device_id)、随机数(ts=123456)等,通常不影响页面实际内容。若直接用 $request_uri,一个带 5 种 UTM 组合的首页会被缓存 5 次。
- 用
map指令预处理 URL,剥离干扰参数:
map $args $clean_args {
~^(.*&)?utm_[^&]*(&.*)?$ "$1$2";
~^(.*&)?ref=[^&]*(&.*)?$ "$1$2";
default $args;
}
- 在
proxy_cache_key中使用$clean_args替代原始$args;或更彻底——静态页直接去掉$args,只保留$scheme$host$request_uri(不含问号后内容)
按业务维度精准分层区分
同一个 URL 在不同场景下可能返回不同内容,这时 key 必须体现差异;但不能过度细化。
-
终端类型:PC 和 H5 首页结构不同,需区分,但不用完整 UA 字符串(太长且易变),可用简写:
$http_user_agent ~* "Mobile|Android|iPhone" ? "m" : "p" -
地域信息:若首页 banner 按城市展示,key 中加入
$geoip_city或$arg_city;若全国统一,则绝不引入 - 登录态敏感模块:用户昵称、购物车角标等区域应异步加载,主 HTML 缓存 key 中 不包含 Cookie 或 session 相关字段;否则每个用户都缓存一份,命中率为零
避免因头部字段导致缓存分裂
默认情况下,Nginx 会把 Cookie、User-Agent、Accept-Encoding 等头纳入 key 计算逻辑(取决于模块版本与配置)。这极易造成缓存碎片。
- 显式定义 key,不依赖隐式行为:
proxy_cache_key "$scheme$host$uri$is_args$clean_args";—— 明确排除$cookie_*、$http_*等潜在变量 - 如确需按语言或编码区分(如 gzip vs br),可保留
$http_accept_encoding,但要搭配gzip_vary on和add_header Vary Accept-Encoding;,确保浏览器和 CDN 协同 - 对可信后端,若其返回的
Vary: Cookie是冗余的,可用proxy_ignore_headers Vary;主动忽略
验证与收敛 key 设计效果
优化不是一劳永逸,需持续观察 key 实际分布是否合理。
- 在日志中记录 key 的哈希值或截断前缀:
log_format cache_debug '$remote_addr - [$time_local] "$request" $status $upstream_cache_status "$cache_key_hash"';,配合set $cache_key_hash "${scheme}${host}${uri}";(用 ngx_http_set_misc_module 或 Lua) - 抽样分析访问频次最高的 100 个 key:若大量 key 仅因单个参数(如
abtest_id=avsabtest_id=b)而不同,说明该参数仍需过滤 - 上线后对比
$upstream_cache_status中HIT与MISST的比例变化,重点关注高频路径(如首页、商品列表页)











