垃圾缓存源于缓存键设计不当,表现为无效重复条目堆积;须先识别键缺陷(如含易变字段致路径分散、mis/expired频发、小文件泛滥),再分层清理而非清空。

缓存键设计不当导致的垃圾缓存,本质是大量无效、重复或无法命中的缓存条目堆积在磁盘和共享内存中。这类问题不能靠“删光重来”解决,否则会引发回源风暴、句柄残留和命中率断崖下跌。关键在于先识别问题根源,再分层清理:从键结构缺陷入手,收缩无效缓存范围,再安全释放资源。
识别键设计缺陷的典型表现
先确认是否真由 cache_key 引发垃圾缓存:
- 同一业务接口(如
/api/user/123)生成多个不同路径的缓存文件(如/a/b/abc...、/c/d/cde...),说明 key 包含了易变字段(如时间戳、随机 token、未标准化的 query 参数) - 日志中
$upstream_cache_status频繁出现MIS或EXPIRED,但后端响应稳定,大概率是 key 过细导致缓存碎片化 - 缓存目录下存在大量小文件(
修正键设计并阻断新垃圾产生
立即停写错误缓存,避免雪球越滚越大:
- 在对应
location块中临时加入proxy_cache_bypass $arg_nocache;,通过加?nocache=1绕过缓存验证逻辑,快速验证后端是否正常 - 检查并收紧
proxy_cache_key:移除不稳定变量,例如不用$time_iso8601、$request_id、$http_x_forwarded_for;对必须区分的维度(如语言、用户角色),改用可控枚举值($arg_lang而非全量$http_accept_language) - 若使用了
$request_body,确认是否真有必要——POST 缓存极易因空格、换行、编码差异产生不同 key,建议改用 GET 接口或签名摘要(如md5($request_body))替代原始体
安全清理已有垃圾缓存
不直接 rm -rf,而是结合路径特征与内容校验分批处理:
- 利用缓存目录的哈希层级(如
levels=1:2)反向推算问题 key 的常见前缀,例如发现大量/0/*、/f/*目录下文件创建时间集中、大小趋同,可针对性find /var/cache/nginx/0 -type f -size -2k -delete - 对疑似垃圾文件抽样验证:用
head -c 512读取文件头,检查是否包含完整 HTTP 响应(含HTTP/1.1 200和Content-Length),无响应头的直接清理 - 执行
nginx -s reload:强制清空共享内存 keys_zone,使残留索引失效;注意 reload 不删磁盘文件,但后续请求会自然淘汰无文件支撑的条目
长期防控机制
防止同类问题复发,需固化治理手段:
- 在
proxy_cache_path中启用inactive=30m,确保 30 分钟内未被访问的缓存自动清理,抑制低频垃圾堆积 - 为高频接口配置独立
keys_zone,与其他业务隔离,避免垃圾缓存挤占有效空间 - 上线前用脚本模拟 key 生成:对典型 URL + 参数组合批量计算 MD5,观察前缀分布是否集中(理想情况 90% 请求落在前 3–5 个一级目录)











