202410
CDN

CDN缓存穿透的三种死法

CDN缓存失效导致源站被打爆?这三个坑你踩过几个

死法一:缓存雪崩

场景: 大量缓存同时过期,请求直击源站

# 错误配置
location ~* \.(jpg|png|css|js)$ {
    expires 1h;  # 所有文件同时过期
}

# 正确配置  
location ~* \.(jpg|png|css|js)$ {
    expires 1h;
    add_header Cache-Control "public, max-age=3600, stale-while-revalidate=300";
}

解决: 设置随机过期时间 + stale-while-revalidate

死法二:热点数据穿透

场景: 热门内容缓存miss,瞬间并发请求源站

// 源站防护
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
  windowMs: 1000, // 1秒
  max: 10, // 每秒最多10个请求
  keyGenerator: (req) => req.headers['cf-connecting-ip'] || req.ip
});

app.use('/api/hot-data', limiter);

死法三:缓存键冲突

场景: 不同内容使用相同缓存键

# 问题URL
/api/user?id=123&timestamp=1642694400
/api/user?timestamp=1642694400&id=123

# 解决方案:标准化查询参数
location /api/ {
    set $args_sorted '';
    # 使用Lua脚本排序查询参数
    rewrite_by_lua_block {
        local args = ngx.req.get_uri_args()
        local sorted_args = {}
        for k, v in pairs(args) do
            table.insert(sorted_args, k .. "=" .. v)
        end
        table.sort(sorted_args)
        ngx.var.args_sorted = table.concat(sorted_args, "&")
    }
    proxy_cache_key $scheme$proxy_host$uri$args_sorted;
}

救命稻草:源站保护

# 限制回源并发
upstream backend {
    server 127.0.0.1:8080 max_conns=50;
    keepalive 32;
}

# 启用缓存锁
proxy_cache_lock on;
proxy_cache_lock_timeout 5s;
proxy_cache_lock_age 5s;

# 使用陈旧缓存
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;

监控告警

# 关键指标
- 缓存命中率 < 90%
- 回源QPS突增 > 基线3倍  
- 源站5xx错误率 > 1%

记住:CDN不是万能的,源站保护才是王道。