内容分发网络(CDN)是一个网站无论你从东京还是多伦多打开都觉得很快的原因。它是一大批分布在全球的缓存服务器,把你的内容存在物理上离用户很近的地方,这样请求由附近的边缘(edge)返回,而不必跨越大洋去你的源站。CDN 几乎出现在本站每一篇系统设计里——Drive视频流Pastebin——作为吸收读流量的那一层。下面讲它到底怎么工作。

⚡ 速览要点
  • 两大收益:延迟和卸载——内容由附近边缘返回更快(距离更短),而且大多数请求根本到不了源站(负载更小)。
  • 边缘 PoP + anycast/GeoDNS 自动把每个用户路由到最近的接入点。
  • 缓存行为由 HTTP 控制——Cache-Control/TTL 决定什么可缓存、缓存多久;缓存键决定什么算"同一个对象"。
  • 命中 vs 未命中——命中由边缘返回;未命中从源站拉取、缓存后再返回。
  • 拉(惰性)vs 推——拉式 CDN 在首次请求时拉取;推式 CDN 预先上传内容。
  • 失效是最难的部分——用 TTL、显式清除(purge),或带版本/指纹的 URL(cache busting)。
  • 附带:安全——CDN 吸收 DDoS、在边缘终结 TLS、托管 WAF。
tldr

CDN 把你的内容缓存在全球边缘服务器上,并把每个用户路由到最近的那个(anycast/GeoDNS),从而降低延迟、为源站挡流量。HTTP 的 Cache-Control 头和缓存键管理缓存行为;缓存命中由边缘返回,未命中从源站拉取并缓存。难题是失效——用 TTL、purge,或带指纹的 URL 解决。静态资源极易缓存;动态内容靠边缘计算和路由优化。

为什么用 CDN:延迟与卸载

两条物理与经济事实驱动整个设计。第一,距离即延迟:数据以有限速度传播,所以从悉尼到弗吉尼亚某服务器的往返本质就慢,无论那台服务器多快。把一份副本放在离用户 20 公里而非 16000 公里处,能大幅砍掉往返时间。第二,卸载:如果边缘从缓存返回大多数请求,你的源站只看到一小部分流量——一个爆火的页面或热门视频几乎全由边缘服务,源站不会被打垮。给用户降延迟,给源站保命——这就是卖点。

怎么工作:边缘 PoP 与路由

CDN 在全球各数据中心运营接入点(PoP,points of presence)——一簇簇缓存服务器。诀窍是自动把每个用户带到最近的 PoP,主要靠两种方式:anycast(很多 PoP 宣告同一个 IP 地址,互联网路由自然把用户送到拓扑上最近的那个)和 GeoDNS(DNS 根据解析方的位置把 CDN 主机名解析到不同的边缘 IP——见我们的 DNS 文章)。无论哪种,用户都在不知不觉中连到了一个近的边缘。

边缘缓存命中 vs 未命中
用户 → 最近的边缘 PoP
         ├─ 命中  → 从边缘缓存返回         (快,不碰源站)
         └─ 未命中 → 从源站拉取 → 缓存 → 返回
                    (该地区后续请求就都是命中了)

  目标:最大化命中率 → 大多数流量在边缘返回

缓存行为:控制、TTL 与键

边缘缓存什么、缓存多久,由源站发出的 HTTP 头控制。Cache-Control: max-age=3600 表示"可缓存一小时";no-store 表示"绝不缓存";stale-while-revalidate 让边缘在后台刷新时先返回稍旧的副本——很适合保持响应快速。

cache-control 头
Cache-Control: public, max-age=31536000, immutable   # 带指纹的资源,缓存 1 年
Cache-Control: public, max-age=60, stale-while-revalidate=300
Cache-Control: no-store                              # 绝不缓存(用户专属)

同样重要的是缓存键(cache key)——CDN 用它判断两个请求是不是"同一个对象"。默认是 URL,但可以包含查询串、头或 cookie。搞错了,要么缓存太粗(返回错的变体),要么太细(每个请求都是唯一键 → 命中率趋近于零)。缓存键基数过高是经典的 CDN 自坑。

推式 vs 拉式 CDN

方面拉式 CDN推式 CDN
内容如何到达惰性,首次请求时(未命中→源站)你上传/预加载到 CDN
首次请求较慢(缓存未命中)快(已在边缘)
最适合大型、常变的目录大文件、可预测的热门内容
工作量低——把 DNS 指向 CDN 即可较高——管理上传/过期

拉式是常见默认(配好就不用管);推式适合你确定会火、又不想首次未命中变慢的大媒体。

失效:最难的部分

"计算机科学只有两件难事:缓存失效和命名。"内容一旦缓存在几百个边缘,更新它就真的很棘手。三种策略,精确度递增:

最优模式

对静态资源,组合用immutable + 指纹 URL:把 app.<hash>.js 缓存一年,从一个短 TTL 的 HTML 页面引用新的哈希。你拿到了最大化缓存且零失效——发布只是指向新文件名。这正是构建工具给资源名加哈希的原因。

静态 vs 动态内容

静态内容——图片、CSS/JS、视频分片、下载——是 CDN 的看家本领:它对所有人都一样、可长时间缓存。动态内容(个性化页面、API 响应)更难,因为因人而异,但 CDN 仍能帮忙,靠动态加速:保持从边缘到源站的预热、优化过的连接(TLS 已协商、走 CDN 骨干的更优路由),以及越来越多的边缘计算——在 PoP 上跑代码来个性化、拼装或缓存片段,离用户更近。"CDN" 和"边缘平台"的界限正因此变得模糊。

安全附带收益

因为 CDN 挡在你源站前面、吸收所有入站流量,它天然是一道安全层:它用庞大容量在攻击到达你之前吸收 DDoS、在边缘终结 TLS(离用户更近、握手更快),还常托管 WAF(Web 应用防火墙)和机器人缓解。对很多站点,光是 DDoS 防护就足以证明上 CDN 的价值。

用途与常见坑

总结

CDN 用一点复杂度(缓存头、失效)换两个大收益:更低延迟(内容离用户近)和源站卸载(大多数请求到不了你)。用 anycast/GeoDNS 把用户路由到最近边缘,用 Cache-Control 和好的缓存键控制缓存,用指纹 immutable URL 绕开失效,顺便也把安全交给边缘。

🎯 面试速答

CDN 给你什么?更低延迟(从附近边缘返回)和源站卸载(大多数读由缓存服务,源站扛得住峰值)。
用户怎么被路由到最近边缘?anycast(很多 PoP 共享一个 IP,路由选最近的)或 GeoDNS(DNS 返回区域专属的边缘 IP)。
推式 vs 拉式 CDN?拉式首次请求时惰性缓存(简单、首次未命中慢);推式预加载内容(首次即命中、管理更多)。
怎么让缓存内容失效?TTL 过期、显式 purge,或——静态最佳——指纹 immutable URL,改动即新 URL、无需失效。
什么是缓存击穿?热门对象过期时很多边缘同时未命中压垮源站;用 stale-while-revalidate、抖动 TTL 或请求合并修复。

← 上一篇
向量数据库