一、为什么我的缓存突然不工作了?
最近遇到一个挺有意思的问题:明明配置了Nginx反向代理缓存,但用户老是抱怨网站加载慢。一查日志,发现缓存根本没生效,所有请求都打到后端服务器去了。这就像你买了台新冰箱,结果发现它根本不制冷,食物全坏了——既浪费电又糟心。
这种情况通常有三大元凶:
- 缓存配置写错了(比如路径权限不对)
- 响应头设置有问题(比如后端强行禁用缓存)
- 缓存键设计不合理(比如每个请求都生成新key)
先看个典型错误配置示例(技术栈:Nginx 1.18 + Ubuntu 20.04):
proxy_cache_path /tmp/nginx_cache levels=1:2 keys_zone=my_cache:10m inactive=60m;
server {
location / {
proxy_cache my_cache;
proxy_pass http://backend;
# 错误1:没有设置缓存状态头
add_header X-Cache-Status $upstream_cache_status;
# 错误2:缓存key只用$uri,忽略查询参数
proxy_cache_key "$uri";
}
}
这个配置有两个致命问题:首先我们看不到缓存是否命中(缺少X-Cache-Status),其次商品详情页的?id=123和?id=456会被当作同一个页面缓存。就像图书馆把所有同名书归到同一书架,找书时肯定要乱套。
二、让缓存乖乖听话的秘诀
要让缓存正常工作,得掌握这几个核心配置:
1. 完整的缓存路径配置
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=hot_cache:100m
inactive=24h max_size=10g use_temp_path=off;
levels=1:2:创建三层子目录(防止单个目录文件过多)max_size=10g:磁盘缓存上限(建议SSD分区)use_temp_path=off:避免临时文件导致的性能损耗
2. 智能缓存键设计
proxy_cache_key "$scheme$request_method$host$request_uri$cookie_user";
包含协议、请求方法、域名、完整路径和用户cookie。就像超市储物柜,用购物小票上的条形码当钥匙,既不会拿错也不会重复。
3. 缓存过滤规则
proxy_cache_valid 200 302 10m; # 成功页面缓存10分钟
proxy_cache_valid 404 1m; # 404页面缓存1分钟
proxy_cache_valid any 5s; # 其他状态码极短缓存
# 不缓存管理员后台
if ($request_uri ~* "^/admin") {
set $do_not_cache 1;
}
proxy_cache_bypass $do_not_cache;
三、那些年我们踩过的坑
案例1:动态API被意外缓存
有个电商平台的商品价格API突然不更新了,查了半天发现是Nginx把GET请求全缓存了。解决方法是在location里添加:
# 只缓存静态资源
location ~* \.(jpg|css|js)$ {
proxy_cache hot_cache;
expires 7d;
}
# 不缓存API接口
location /api {
proxy_pass http://backend;
proxy_no_cache 1; # 强制不缓存
}
案例2:Cookie导致缓存碎片化
用户登录后每个请求都带唯一sessionid,导致缓存命中率几乎为零。解决方案是清洗缓存key:
map $http_cookie $parsed_cookie {
default "";
"~*user_token=(?<token>[^;]+)" $token;
}
proxy_cache_key "$host$request_uri$parsed_cookie";
四、高级玩家必备技巧
1. 缓存预热策略
在服务器启动时自动加载热门内容:
# 预热脚本preheat.sh
URLS=("/hot-product" "/news" "/featured")
for url in "${URLS[@]}"; do
curl -s -o /dev/null "http://localhost${url}"
done
2. 分层缓存策略
# 内存级热点缓存(存放访问频次最高的内容)
proxy_cache_path /dev/shm/micro_cache levels=1:2 keys_zone=micro:5m max_size=100m;
# 普通磁盘缓存
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=main:100m max_size=10g;
location / {
# 先查内存缓存
proxy_cache micro_cache;
proxy_cache_valid 200 1m;
# 内存未命中再查磁盘缓存
error_page 404 = @fallback;
}
location @fallback {
proxy_cache main;
proxy_cache_valid 200 1h;
}
3. 缓存状态监控
location /cache-status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
配合Prometheus的nginx_exporter可以实时监控:
- 缓存命中率
- 缓存使用量
- 过期项目数量
五、终极解决方案清单
当遇到缓存问题时,按照这个checklist排查:
- 检查磁盘空间
df -h /var/cache/nginx - 验证目录权限
ls -ld /var/cache/nginx - 查看响应头
curl -I http://example.com | grep Cache - 检查错误日志
tail -f /var/log/nginx/error.log - 强制刷新缓存
curl -X PURGE http://example.com/resource
记住,好的缓存策略应该像优秀的餐厅服务员——熟客来了直接上常点的菜,新客人则耐心询问需求。既提升效率又保持灵活性,这才是Nginx缓存配置的艺术。
评论