题目
设计高并发场景下的Nginx缓存策略并解决缓存穿透、雪崩和击穿问题
信息
- 类型:问答
- 难度:⭐⭐⭐
考点
Nginx缓存机制,缓存异常场景处理,高并发优化,动态内容缓存
快速回答
核心解决方案要点:
- 基础缓存配置:使用
proxy_cache_path定义缓存区域,proxy_cache启用缓存 - 缓存穿透:通过
proxy_cache_bypass过滤无效请求,结合空值缓存和Bloom过滤器 - 缓存雪崩:设置随机过期时间
proxy_cache_valid,启用缓存锁proxy_cache_lock - 缓存击穿:使用
proxy_cache_lock实现请求合并,后端熔断机制 - 动态内容:
proxy_cache_key包含会话参数,proxy_ignore_headers忽略Set-Cookie
1. 核心问题背景
在高并发场景下(如秒杀系统),Nginx缓存需要应对:
- 缓存穿透:恶意请求不存在的数据
- 缓存雪崩:大量缓存同时失效导致后端压力骤增
- 缓存击穿:热点key失效瞬间大量请求直达后端
2. Nginx缓存基础配置
# 定义缓存路径及参数
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=my_cache:10m
inactive=60m max_size=1g use_temp_path=off;
server {
location / {
proxy_pass http://backend;
proxy_cache my_cache; # 启用缓存
proxy_cache_valid 200 302 10m; # 成功状态码缓存10分钟
proxy_cache_valid 404 1m; # 缓存空结果
# 缓存键设计(包含必要参数)
proxy_cache_key "$scheme$request_method$host$request_uri$arg_user_id";
# 缓存锁定(防击穿)
proxy_cache_lock on;
proxy_cache_lock_timeout 5s;
# 跳过缓存条件(防穿透)
proxy_cache_bypass $http_pragma $http_authorization;
}
}3. 针对性解决方案
3.1 缓存穿透
- 空值缓存:缓存404响应(
proxy_cache_valid 404 1m) - 请求过滤:
# 在Nginx中实现基础Bloom过滤器(需Lua模块支持) location / { access_by_lua_block { local bloom = require "resty.bloom" local bf = bloom:new(1000000, 0.01) -- 从数据库加载有效key到bf(实际需定时更新) if not bf:get(ngx.var.request_uri) then return ngx.exit(404) end } }
3.2 缓存雪崩
- 随机过期时间:
# 在缓存有效时间上增加随机扰动 map $status $cache_time { default 0; 200 600; # 基础10分钟 } proxy_cache_valid 200 $cache_time+$request_time; # 加入请求时间作为随机因子 - 分级缓存:L1内存缓存 + L2磁盘缓存
3.3 缓存击穿
- 请求合并:启用
proxy_cache_lock后,首个请求回源时其他请求等待 - 后端熔断:
# 结合limit_req模块限制到后端的请求 location /backend { limit_req zone=backend_burst burst=10 nodelay; proxy_pass http://backend_upstream; # 熔断机制(需lua-resty-circuitbreaker) proxy_next_upstream error timeout http_500; }
4. 动态内容缓存实践
- 个性化内容:在
proxy_cache_key中包含用户ID等必要参数 - Cookie处理:
# 忽略Set-Cookie头防止缓存失效 proxy_ignore_headers Set-Cookie; # 但需排除敏感路径 location /checkout { proxy_cache off; }
5. 常见错误与优化
- 错误1:未设置
max_size导致磁盘写满 → 监控缓存目录大小 - 错误2:缓存键未包含变化参数 → 使用
$query_string或关键参数 - 优化1:启用
proxy_cache_revalidate用If-Modified-Since验证旧缓存 - 优化2:使用
proxy_cache_use_stale在更新时返回旧缓存
6. 扩展知识
- 缓存分片:通过
proxy_cache_path的levels参数优化文件查找 - Purge机制:使用
proxy_cache_purge模块实现主动清理 - 性能监控:通过
nginx-module-vts监控缓存命中率