强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

CDN 与 WAF 精讲教程 / 第04章 缓存策略

第04章 缓存策略

缓存是 CDN 的核心能力。本章全面讲解缓存规则设计、缓存键(Cache Key)构造、缓存失效机制、预热策略以及分层缓存架构。


4.1 缓存规则

4.1.1 缓存规则类型

CDN 通常支持多层级缓存规则匹配:

优先级匹配维度示例
1(最高)完整 URL 路径/api/user/profile
2URL 路径前缀/static/
3文件扩展名*.jpg, *.js
4请求头Cookie / Authorization
5(最低)默认规则/*

4.1.2 常见缓存规则配置

┌─────────────────────────────────────────────────────────────┐
│                    缓存规则矩阵                              │
├──────────────┬────────┬─────────────┬───────────────────────┤
│ 资源类型      │ TTL    │ 缓存级别     │ 更新方式              │
├──────────────┼────────┼─────────────┼───────────────────────┤
│ HTML 页面    │ 60-300s│ 边缘 + 中间层│ 文件名不变            │
│ CSS/JS       │ 1 年   │ 全层级       │ 文件名带 hash         │
│ 图片         │ 30 天  │ 全层级       │ 主动 Purge            │
│ API (GET)    │ 0-60s  │ 仅边缘       │ 短 TTL + 主动失效     │
│ API (POST)   │ 不缓存 │ —           │ —                     │
│ 视频 (HLS)   │ 1-7 天 │ 全层级       │ 片段级更新            │
│ 字体         │ 1 年   │ 全层级       │ 版本号变更            │
│ 文档 (PDF)   │ 7 天   │ 全层级       │ URL 变更 / Purge      │
└──────────────┴────────┴─────────────┴───────────────────────┘

4.1.3 条件缓存规则

# Nginx 缓存规则示例
location ~* \.(jpg|jpeg|png|gif|webp|avif|ico)$ {
    expires 30d;
    add_header Cache-Control "public, immutable";
    add_header CDN-Cache-Control "max-age=2592000";
}

location ~* \.(css|js)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

location /api/ {
    # 不缓存 API 请求
    add_header Cache-Control "no-store";
    add_header CDN-Cache-Control "no-store";
}

location / {
    # 首页短缓存
    expires 5m;
    add_header Cache-Control "public, s-maxage=300, stale-while-revalidate=60";
}

4.2 缓存键(Cache Key)

4.2.1 什么是缓存键

Cache Key 是 CDN 用来标识和查找缓存对象的唯一标识符。两个请求如果 Cache Key 相同,则它们会共享同一份缓存。

4.2.2 默认缓存键

默认 Cache Key = Scheme + Host + Port + Path + Query String

示例:
  https://example.com:443/style/main.css?v=2
  ├── scheme: https
  ├── host: example.com
  ├── port: 443
  ├── path: /style/main.css
  └── query: ?v=2

  完整键: "https:example.com:443:/style/main.css?v=2"

4.2.3 自定义缓存键策略

策略适用场景说明
忽略查询参数SPA 应用?utm_source 等追踪参数不影响内容
忽略特定参数电商只保留影响内容的参数
包含设备类型响应式网站PC / Mobile 不同内容
包含语言多语言网站Accept-Language 影响内容
包含 Cookie个性化内容需注意缓存碎片化
忽略端口默认端口80/443 不应产生不同缓存

4.2.4 缓存键设计陷阱

❌ 错误示例:完整查询参数作为缓存键

  /product?id=123&ref=google
  /product?id=123&ref=baidu
  /product?id=123&ref=wechat

  → 同一商品页面产生 3 份缓存!(缓存碎片化)

✅ 正确示例:忽略无关参数

  Cache Key = Path + "id" 参数

  /product?id=123  → 只产生 1 份缓存

4.3 缓存失效(Cache Invalidation)

4.3.1 失效方式

方式原理适用场景粒度
TTL 过期缓存超过 max-age 后自动失效通用被动
主动 Purge手动/API 触发清除缓存内容更新URL / 标签 / 全局
版本化 URL文件名中嵌入 hash,新版本用新 URLCSS/JS 部署精确
Purge-Soft标记为过期,下次请求异步回源灰度发布URL

4.3.2 主动 Purge API 示例

# Cloudflare Purge by URL
curl -X POST "https://api.cloudflare.com/client/v4/zones/{zone_id}/purge_cache" \
  -H "Authorization: Bearer {api_token}" \
  -H "Content-Type: application/json" \
  --data '{"files":["https://example.com/style/main.css"]}'

# Cloudflare Purge by Tag (Cache-Tag)
curl -X POST "https://api.cloudflare.com/client/v4/zones/{zone_id}/purge_cache" \
  -H "Authorization: Bearer {api_token}" \
  -H "Content-Type: application/json" \
  --data '{"tags":["product-123","category-books"]}'

# 阿里云 CDN 缓存刷新
aliyun cdn RefreshObjectCaches \
  --ObjectPath "https://example.com/style/main.css" \
  --ObjectType File

4.3.3 版本化 URL 策略

<!-- 文件名嵌入 hash:每次构建生成新文件名 -->
<link rel="stylesheet" href="/static/css/main.a1b2c3d4.css">
<script src="/static/js/app.e5f6g7h8.js"></script>

<!-- 优势:
  1. 无需 Purge 旧缓存
  2. 可设置 max-age=1 年(immutable)
  3. 新版本自动使用新 URL → 新缓存
  4. 回滚只需恢复旧 HTML 中的引用
-->

4.4 缓存预热(Cache Preheat)

4.4.1 预热场景

场景时间说明
大促活动活动前 1-2 小时提前缓存活动页面、商品图片
版本发布发布时新 CSS/JS 推送到边缘
热点内容突发事件新闻/短视频爆发前预热
新站上线上线前首次访问不至于全部 MISS

4.4.2 预热流程

预热流程:

  ┌──────────────┐
  │ 预热任务触发  │  手动/API/定时
  └──────┬───────┘
         ▼
  ┌──────────────┐
  │  URL 列表    │  需要预热的资源清单
  └──────┬───────┘
         ▼
  ┌──────────────┐
  │ 分批推送     │  控制并发,避免打爆源站
  │ 100 URL/批   │
  └──────┬───────┘
         ▼
  ┌──────────────┐
  │ 边缘节点回源  │  模拟 Cache Miss → 回源获取
  └──────┬───────┘
         ▼
  ┌──────────────┐
  │ 缓存写入     │  存入边缘缓存存储
  └──────┬───────┘
         ▼
  ┌──────────────┐
  │ 验证命中率    │  抽样检查 HIT 状态
  └──────────────┘

⚠️ 注意:预热应在流量低峰期进行,避免回源风暴。建议分批执行,每批间隔 1-2 分钟。


4.5 分层缓存(Tiered Caching)

4.5.1 分层缓存架构

┌──────────────────────────────────────────────────────────────────┐
│                        分层缓存架构                               │
│                                                                  │
│  用户请求                                                         │
│     │                                                            │
│     ▼                                                            │
│  ┌────────────────────┐                                          │
│  │  边缘缓存 (L1)     │  命中率: 60-85%                          │
│  │  特点: 最近、最快   │  存储: 热点数据                          │
│  └────────┬───────────┘                                          │
│           │ MISS                                                 │
│           ▼                                                      │
│  ┌────────────────────┐                                          │
│  │  中间层缓存 (L2)   │  额外命中: 10-20%                        │
│  │  Shield 节点       │  存储: 温数据                             │
│  └────────┬───────────┘                                          │
│           │ MISS                                                 │
│           ▼                                                      │
│  ┌────────────────────┐                                          │
│  │  源站 (L3)         │  最终来源                                 │
│  │  数据库 / Object   │                                         │
│  └────────────────────┘                                          │
│                                                                  │
│  总体命中率: 70-99%(取决于内容类型和访问模式)                    │
└──────────────────────────────────────────────────────────────────┘

4.5.2 Shield 回源盾

Shield(回源盾) 是分层缓存的关键组件。在众多边缘节点中,指定一个(或少数几个)节点作为统一回源入口:

特性无 Shield有 Shield
回源请求数N 个节点 × 各自回源1 次统一回源
源站压力极低
缓存命中率各节点独立Shield 汇聚共享
跨区域延迟Shield 到源站优化路由
故障影响仅影响单个 PoPShield 故障影响所有

4.5.3 缓存命中率优化

优化手段说明预期提升
扩大缓存范围更多资源类型纳入缓存+5-15%
延长 TTL从 1 小时提升到 1 天+10-20%
Vary 头精简减少 Vary 维度+5-10%
回源合并防止并发回源重复+0%(减少源站压力)
启用 Shield跨节点共享缓存+10-20%
忽略无关参数优化 Cache Key+5-15%

4.6 高级缓存模式

4.6.1 边缘侧包含(ESI)

ESI(Edge Side Includes) 允许在 CDN 边缘组装页面的不同部分:

<!-- 主页面缓存 5 分钟 -->
<html>
<body>
    <!-- 头部:缓存 1 小时 -->
    <esi:include src="/fragment/header" ttl="3600"/>

    <!-- 内容:缓存 5 分钟 -->
    <esi:include src="/fragment/content?id=123" ttl="300"/>

    <!-- 推荐:缓存 30 秒(高频变化) -->
    <esi:include src="/fragment/recommendations" ttl="30"/>
</body>
</html>
优点缺点
页面各部分独立缓存,提高命中率仅部分 CDN 厂商支持
减少回源传输量增加边缘处理复杂度
个性化 + 缓存兼得调试困难

4.6.2 负面缓存(Negative Caching)

# 对 404 响应短时间缓存,防止缓存穿透
location / {
    proxy_cache_valid 200 301 302 10m;
    proxy_cache_valid 404 1m;       # 404 缓存 1 分钟
    proxy_cache_valid any 5m;
}
场景策略原因
404 Not Found缓存 1-5 分钟防止缓存穿透
5xx Error不缓存或极短缓存允许快速恢复
302 Redirect缓存重定向减少重复解析

4.7 注意事项

⚠️ 缓存一致性:CDN 缓存是最终一致性模型。主动 Purge 也需要一定时间传播到全球节点。

⚠️ 私有内容:包含 Authorization 头的请求默认不缓存。如需缓存,务必确认无敏感信息泄露。

⚠️ Set-Cookie 响应:带有 Set-Cookie 的响应通常会被 CDN 跳过缓存。如果需要缓存,应在源站剥离 Cookie。

⚠️ Vary: Cookie:此设置会导致每个不同的 Cookie 值生成一份缓存,极易导致缓存命中率崩塌。


4.8 扩展阅读


本章小结

主题核心要点
缓存规则按 URL/路径/扩展名分层配置 TTL
缓存键合理设计避免缓存碎片化
缓存失效TTL + 主动 Purge + 版本化 URL
预热大促/发布前主动推送缓存
分层缓存L1(Edge) + L2(Shield) + L3(Origin)

下一章:第05章 CDN 性能优化 →