高并发缓存穿透防控核心是精准命中与分流:通过$upstream_cache_status定位bypass/miss/expired原因,清洗uri参数收敛key,启用proxy_cache_lock+stale兜底击穿,分层bypass动态请求。

高并发下缓存绕过直接导致穿透,核心不是“堵住所有绕过”,而是让真正该缓存的请求稳稳命中、不该缓存的干脆不进缓存路径——减少无效回源,才是降低性能损耗的关键。
精准识别并收敛绕过源头
多数穿透不是配置没开,而是被隐式跳过。先确认真实原因,再针对性处理:
- 检查
$upstream_cache_status日志字段:BYPASS表示被指令绕过,MISS是未命中,EXPIRED是过期——三者处理策略完全不同 - 用
curl -I查响应头:X-Cache: BYPASS配合Set-Cookie、Authorization、Cache-Control: no-cache等头,基本能定位是否因请求头触发默认 bypass 规则 - 上游返回含
Cache-Control: private或no-store时,Nginx 默认不缓存;可加proxy_ignore_headers Cache-Control Set-Cookie;(仅限可信后端)
收紧 cache_key,避免“伪唯一”击穿
URI 带随机参数(如 ?t=123456、&_v=abc)会让每个请求生成不同 key,表面是 MISS,实则是自建穿透陷阱:
- 用
set+if清洗 URI:set $cache_uri $uri;,再匹配并剔除时间戳类参数,统一使用净化后的$cache_uri构建 key - 避免在
proxy_cache_key中引入易变变量,如$cookie_sessionid、$arg_token;静态资源 key 至少应基于$host$uri或$host$scheme$request_method$uri - 对 API 接口,若需区分用户态但又想复用缓存,可将权限级别(如
role=guest)纳入 key,而非具体用户 ID
用 lock + stale 组合兜底热点穿透
即便 key 收敛了,突发流量仍可能在缓存失效瞬间引发多请求并发回源——这是典型的缓存击穿,需主动防御:
- 开启
proxy_cache_lock on;:只允许一个请求回源,其余等待锁释放后直接读缓存 - 设
proxy_cache_lock_timeout 3s;:避免锁持有过久,超时后其他请求也允许回源(防雪崩) - 搭配
proxy_cache_use_stale error timeout updating;:在更新中、超时或错误时,仍可返回旧缓存,保障可用性 - 对极低频接口,加
proxy_cache_min_uses 2;:只缓存至少被访问两次的资源,过滤掉扫描、调试等噪声流量
分层过滤,让穿透止于边缘
不是所有请求都值得走 proxy_cache 流程。在进入缓存逻辑前,用轻量规则快速分流:
- 登录页、购物车、POST 请求等明确动态内容,直接
proxy_cache_bypass true;跳过缓存层 - 按 Cookie 或 Header 判断:如含
user_id=或X-Debug:1,统一 bypass:proxy_cache_bypass $cookie_user_id $http_x_debug; - 对已知高频但无需强一致的资源(如首页推荐位),可单独配置更长
inactive(如inactive=120m),配合proxy_cache_valid 200 30m;,延长实际驻留时间











