Nginx无法动态生成缓存目录名,但可通过map构造带维度标识的proxy_cache_key实现逻辑隔离;配合多keys_zone和cache purge可达成多维缓存管理与精准清理。

不能直接用 map 指令生成缓存目录名,Nginx 的 proxy_cache_path 中的 levels 和 keys_zone 是静态定义的,目录结构由哈希值自动计算,不支持运行时拼接路径或变量命名。但可以通过 map 动态构造缓存键(proxy_cache_key),再配合合理的 key 设计,让相同维度的资源落入逻辑上“可区分”的缓存槽位——这虽不改变物理目录名,却能实现多维度资源的隔离存储与独立失效,效果等价于精细化目录管理。
用 map 构造带维度标识的缓存 key
核心思路是把请求特征(如域名、设备类型、语言、版本参数)编码进 proxy_cache_key,使不同维度组合产生唯一哈希输入,从而自然分散到不同缓存条目中。
- 在
http块中定义多个维度变量:
map $http_user_agent $device_type {
default "desktop";
~*mobile|android|iphone "mobile";
~*ipad|tablet "tablet";
}
map $host $site_group {
"a.example.com" "site_a";
"b.example.com" "site_b";
default "common";
}
map $arg_v $version_tag {
"" "v1";
~*^([0-9]+)\.([0-9]+) "$1.$2";
}
- 在
location中组合 key:
location ~* \.(js|css|png|jpg|webp)$ {
proxy_pass http://origin;
proxy_cache my_cache;
proxy_cache_key "$scheme$request_method$host$request_uri$device_type$site_group$version_tag";
proxy_cache_valid 200 302 1d;
}
这样,https://a.example.com/main.js?v=2.1(手机访问)和 https://b.example.com/main.js?v=2.1(桌面访问)将生成完全不同的缓存 key,互不影响。
按维度分组缓存区域(keys_zone 隔离)
若需更强隔离(比如移动端缓存必须独立过期、不与桌面共享),可为不同维度预设多个 keys_zone,再用 map 选择使用哪个:
- 定义缓存区:
proxy_cache_path /var/cache/nginx/site_a levels=1:2 keys_zone=site_a:10m; proxy_cache_path /var/cache/nginx/site_b levels=1:2 keys_zone=site_b:10m; proxy_cache_path /var/cache/nginx/mobile levels=1:2 keys_zone=mobile:5m;
- 用 map 映射 zone 名:
map $site_group $cache_zone {
"site_a" "site_a";
"site_b" "site_b";
default "mobile";
}
# 或更细粒度:map $device_type$site_group $cache_zone { ... }
- 在 location 中引用:
proxy_cache $cache_zone;
此时不同维度实际写入不同物理缓存区,目录结构虽仍由哈希决定,但已实现“逻辑目录分离”。
配合 cache purge 实现维度级清理
真实目录名不可控,但可通过第三方模块(如 ngx_cache_purge)或 OpenResty 的 lua-resty-limit-traffic + 自定义 key 规则,按维度批量清理:
- 例如,所有
mobile请求的 key 都含$device_type,清理时可匹配*mobile*前缀(需模块支持通配); - 更稳妥方式:在应用层记录各维度 key 模板,定时调用 purge 接口清除指定模式。
为什么不直接改目录名?
Nginx 缓存目录由 MD5(proxy_cache_key) 自动切片生成(如 ab/cdef1234567890...),这是为高性能哈希查找设计的,硬编码路径会破坏一致性哈希机制,导致缓存命中率归零。所以“动态目录名”本质是伪需求,真正要解决的是“逻辑维度隔离”,而 map + cache_key + keys_zone 组合已足够达成目标。










