Nginx代理缓存的工作机制与缓存键设计
Nginx的proxy_cache模块将上游服务器响应缓存到本地磁盘,后续相同请求直接从缓存返回,减少回源压力。缓存的匹配依赖缓存键(cache key),默认值为请求的完整URL。缓存键的粒度决定了缓存的命中率与有效性。
缓存键的构成要素包括请求方法、URI、查询参数,甚至可以加入Cookie或Accept-Encoding头,实现按客户端状态的缓存分片。但键越复杂,命中率越低,需要在命中率和个性化之间取平衡。
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=main:100m
max_size=10g inactive=60m use_temp_path=off;
server {
location /api/ {
proxy_cache main;
proxy_cache_key $scheme$proxy_host$request_uri;
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_use_stale error timeout updating http_500;
proxy_cache_lock on;
proxy_cache_lock_timeout 5s;
add_header X-Cache-Status $upstream_cache_status;
proxy_pass http://backend;
}
}
proxy_cache_path的levels=1:2参数将缓存文件分散到两级子目录,避免单目录文件数过多导致文件系统性能退化。keys_zone定义共享内存区域,存储缓存键和元数据,100MB约能管理80万条缓存索引。
多级缓存策略与缓存层级设计
在高并发架构中,单层缓存难以同时满足命中率和新鲜度要求。多级缓存策略将不同时效的内容分布到不同缓存层:
第一级:本地内存缓存,使用open_file_cache缓存文件句柄和元数据,减少磁盘IO。适合静态资源和小体积API响应。
第二级:磁盘缓存proxy_cache,缓存中等时效的动态内容,TTL 5-60分钟。
第三级:CDN边缘缓存,将静态资源和长时效内容推送到距离用户最近的边缘节点。
proxy_cache_path /var/cache/nginx/fast keys_zone=fast:50m
max_size=2g inactive=5m;
proxy_cache_path /var/cache/nginx/slow keys_zone=slow:200m
max_size=20g inactive=60m;
location /api/feed/ {
proxy_cache fast;
proxy_cache_valid 200 5m;
proxy_pass http://backend;
}
location /api/articles/ {
proxy_cache slow;
proxy_cache_valid 200 60m;
proxy_pass http://backend;
}
inactive参数控制缓存文件的过期时间,如果文件在inactive时间内没有被访问则自动删除。proxy_cache_valid控制的是缓存的新鲜度时间,过期后下次请求触发回源验证。
缓存锁与雪崩防护机制
当缓存过期时,大量并发请求同时穿透到上游,形成缓存雪崩。proxy_cache_lock是Nginx内置的防雪崩机制:第一个请求回源并填充缓存,其余请求等待缓存填充完成后直接命中。
proxy_cache_lock on;
proxy_cache_lock_timeout 5s;
proxy_cache_lock_age 5s;
proxy_cache_lock_age定义单次回源的最大时长,超时后释放锁让下一个请求重新回源。这个值不宜设置过大,否则某个慢请求会阻塞所有等待中的请求。
proxy_cache_use_stale允许在回源失败时返回过期缓存,这是容灾的关键配置:
proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504 updating;
updating状态码表示缓存正在被更新,此时返回过期缓存而不是等待更新完成。配合proxy_cache_background_update可以实现异步刷新:
proxy_cache_background_update on;
缓存清除与强制刷新机制
Nginx不提供按URL清除缓存的内置命令,但可以通过自定义缓存键实现等效功能。在缓存键中加入版本号参数,更新版本号即可让旧缓存失效:
proxy_cache_key $scheme$proxy_host$request_uri$v_cache_version;
set $v_cache_version "v1";
if ($arg_nocache) {
set $v_cache_version "v2";
}
更精确的控制使用purge模块。ngx_cache_purge是第三方模块,支持按URL正则批量清除缓存:
location ~ /purge(/.*) {
allow 10.0.0.0/8;
deny all;
proxy_cache_purge main $scheme$proxy_host$1;
}
清除缓存的接口必须严格限制访问来源,避免被恶意利用导致回源风暴。
缓存命中率监控与性能调优
upstream_cache_status变量记录每次请求的缓存命中状态:HIT、MISS、EXPIRED、STALE、BYPASS、REVALIDATED。在日志中记录这个变量,用goaccess或自研脚本统计命中率:
log_format cached "$remote_addr - [$time_local] "
""$request" $status $body_bytes_sent "
""$http_user_agent" $upstream_cache_status";
access_log /var/log/nginx/access.log cached;
命中率低于80%时,检查缓存键是否包含过多变量、TTL是否过短、缓存空间是否不足。max_size耗尽后Nginx按LRU淘汰缓存,热点内容可能被频繁淘汰。
磁盘IO是缓存性能的瓶颈。将缓存目录放在SSD或NVMe上,配合use_temp_path=off避免临时文件跨设备拷贝。内核参数中vm.dirty_ratio和vm.dirty_background_ratio的调优也很关键,脏页回写频率过高会导致缓存写入卡顿。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/nginx-fan-xiang-dai-li-huan-cun-pei-zhi-yu-proxycache-duo/