时间戳参数(如?t=、_ts=)导致缓存失效,因nginx默认将完整url作为缓存键;应使用map指令清洗无意义时间参数,构造稳定cache_key,并区分实时接口特殊处理。

带时间戳的请求(比如 ?t=1718234567 或 &_ts=1690872345)是缓存命中率低的常见元凶——它让同一页面每次生成不同缓存键,导致缓存完全失效。
为什么时间戳会破坏缓存一致性
时间戳参数本身不改变响应内容,仅用于绕过浏览器或 CDN 缓存。但若直接用 $args 或默认 $request_uri 构建缓存键,Nginx 会把整个带时间戳的 URL 当作新资源处理,结果:
- 每个请求都写入一个新缓存文件,磁盘迅速膨胀
- keys_zone 内存被海量低价值 key 占满,触发频繁淘汰
- 后端持续被回源,缓存形同虚设
用 map 指令清洗时间戳参数
核心做法:在构建缓存键前,先剥离所有已知无意义的时间类参数,只保留真正影响响应的查询参数。
示例配置(放在 http 块中):
map $args $clean_args {
default "";
"~^(.*&|)(t|_ts|timestamp|nocache|rand)(=[^&]*)?(&.*|)$" "$1$4";
}
说明:
- 正则匹配
t=、_ts=、timestamp=等典型时间戳参数 -
$1和$4分别捕获参数前后的有效部分,实现“剔除不留痕” - 保留如
?s=nginx&page=2这类业务参数,不影响分页或搜索逻辑
构造稳定缓存键并验证效果
使用清洗后的参数构建 key,例如:
fastcgi_cache_key "$scheme$request_method$host$request_uri$is_args$clean_args";
验证是否生效的两个关键动作:
- 在
log_format中加入$cache_key,查 access log,确认相同业务 URL(无论是否带t=xxx)生成的 key 完全一致 - 用
curl -I请求两次:/article/123?t=123和/article/123,观察响应头中X-FastCGI-Cache: HIT是否都出现
补充建议:对必须保留时间语义的场景做区分
极少数情况(如实时行情接口),时间戳确实参与响应生成。此时不应全局剔除,而应:
- 单独为该 location 设置专用 cache key,显式包含
$arg_t并配短缓存时间 - 用
proxy_cache_bypass或fastcgi_cache_bypass让带特定时间戳的请求跳过缓存 - 配合后端返回
Cache-Control: no-store,由 Nginx 尊重响应头自动不缓存











