设想你所在的城市有一家老字号点心铺,总店开在城南工业区。起初,人们为了买一盒绿豆糕,愿意坐四十分钟公交穿城而过。后来点心铺在城东、城西、城北各开了三家社区分店,分店提前备好最畅销的点心,居民下楼就能买到,只有分店缺货时才请总店冷链车补货。这就是 CDN(内容分发网络)最朴素的直觉:把“货”(静态资源)提前铺到离用户最近的“边缘节点”(社区分店),把“补货”(回源)的次数压到最低,用户不再每次穿越整座城市访问源站。你还会发现,聪明的分店会想尽办法让顾客少跑空——提供代收快递、现场加工、定时盘点,这对应着 CDN 的调度、过期策略、边缘计算与故障防御。本篇文章就以这张“社区便利店网络”为地图,带你完整走一遍 CDN 与边缘缓存的原理、实践与面试考点。

岗位关联

学会 CDN 与边缘缓存,你就能看懂架构师口中“命中率”“回源”"TTL"“GSLB“这些黑话背后的取舍逻辑,在高并发面试与生产故障排查中,把”把货备到楼下的智慧”讲得既专业又清晰。

目录
  1. 可视化演示
  2. CDN加速原理
  3. 边缘节点调度
  4. 缓存键设计
  5. 过期策略
  6. 动态内容加速
  7. 边缘网络计算
  8. 性能调优实战
  9. 生产故障排查
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

展示CDN工作流中DNS调度、边缘请求、缓存命中和回源四阶段,Push与Pull两种缓存推送模式,以及缓存键设计与TTL过期策略。

本节配有交互动效(进入视口后自动加载,约 3KB)。

CDN工作流 DNS调度→边缘请求 RTT 200ms→50ms 缓存命中直接返回,未命中则回源拉取。

CDN加速原理

如果你家楼下新开了一家连锁便利店,你还会为了买一瓶酱油专门坐四十分钟公交去大超市吗?大多数人不会,因为“近”本身就是最大的价值。CDN 加速原理就是这句朴素道理的技术版:把图片、CSS、JavaScript、视频这类几乎不变的静态资源,提前复制到遍布各地机房里的“边缘节点”,让用户从家门口的“分店”取货,而不是每次都打车去“总仓”——源站。

这里的“取货”对应一次 HTTP 请求。用户请求到达边缘节点时,如果“分店货架”上正好有这份资源,就直接返回,整个过程不再打扰源站;只有当分店缺货时,边缘节点才回源站取,取完还会在本地留一份,方便下一位邻居。于是“缺货率”越低,用户平均等待时间越短,这个“缺货率”在 CDN 世界里叫回源率。

假设缓存命中率是 \(p\),用户到边缘节点的网络时延是 \(T_{\text{edge}}\),边缘节点再到源站补货的额外时延是 \(T_{\text{back}}\),那么用户请求的平均期望时延可以写成:

CDN 之所以快,不是因为它把网络距离变短了,而是把“走远路”的概率从 100% 降到了 \(1-p\)。就像便利店真正改善生活质量的不是把点心做得多好吃,而是让你在加班回家时,楼下那盏灯还亮着。

Texp=Tedge+(1−p)×Tback\displaystyle T_{\text{exp}} = T_{\text{edge}} + (1 - p) \times T_{\text{back}}
公式说明:用户体感延迟 = 家门口取货的固定耗时 + 缺货时跑去总仓补货的额外耗时 × 缺货概率。 \(p\) 越接近 1,第二项越趋近于 0。
  1. 固定耗时 \(T_{\text{edge}}\)用户到最近边缘节点的一次网络往返时延,这是 CDN 架构下无法消除的“下楼”时间。
    Tedge=RTTuser→edge\displaystyle T_{\text{edge}} = \text{RTT}_{\text{user} \to \text{edge}}
  2. 缺货概率 \((1-p)\)\(p\) 是缓存命中率,即请求在边缘节点直接找到资源的比例;反之 \(1-p\) 就是需要回源的比例。
    p=命中次数总请求次数\displaystyle p = \frac{\text{命中次数}}{\text{总请求次数}}
  3. 补货代价 \(T_{\text{back}}\)边缘节点到源站的额外时延,通常远大于 \(T_{\text{edge}}\),因为数据要穿越骨干网络。
    Tback=RTTedge→origin\displaystyle T_{\text{back}} = \text{RTT}_{\text{edge} \to \text{origin}}

边缘节点调度

当你在手机地图上搜索“最近的便利店”,导航会结合你的位置、道路拥堵和门店营业状态,给你推荐最合适的一家。CDN 里的“导航系统”叫 GSLB(全局负载均衡),它负责回答一个关键问题:用户来了,该把他导向哪个边缘节点?

流程是这样的:用户访问加速域名时,先向本地 DNS 发起解析;本地 DNS 层层递归,最终把请求送到 CDN 服务商的 GSLB 调度器。GSLB 一看请求来源的出口 IP,就知道用户大概在哪个城市,再结合各边缘节点的实时负载与链路质量,返回一个最优边缘节点的 IP。整个过程对用户透明,就像你只说了句“我要买酱油”,导航默默帮你规划了路线。

调度器的最优选择可以抽象为一个最优化问题:从候选边缘节点集合中,选出与用户之间往返时延最小的那一个。

GSLB 还会综合节点负载、带宽成本、可用性等做加权决策,避免把所有人都导到同一家“网红店”门口排队。调度的艺术,本质上就是让每位顾客都知道最近、最空、最稳的那家分店在哪。

i∗=arg⁡min⁡i{RTT(user,edgei)}\displaystyle i^{*} = \arg\min_{i} \{ \text{RTT}(\text{user}, \text{edge}_{i}) \}
公式说明:GSLB 是“货比三家”的理性顾客,遍历所有开着的分店,挑一家离自己最近、路上不堵的去。
  1. 候选集合 \(\text{edge}_i\)CDN 厂商在全球部署的众多边缘节点,每个节点覆盖一片区域。
    i∈{1,2,…,N}\displaystyle i \in \{1, 2, \dots, N\}
  2. 往返时延 \(\text{RTT}(\text{user}, \text{edge}_i)\)衡量用户与第 \(i\) 个节点之间网络“距离”的指标,比物理距离更真实。
    RTT=treq+tresp\displaystyle \text{RTT} = t_{\text{req}} + t_{\text{resp}}
  3. \(\arg\min\) 取最优在所有候选者中选出使 RTT 最小的下标 \(i^{*}\),这就是返回给用户 DNS 解析结果的边缘节点。
    i∗=arg⁡min⁡i{… }\displaystyle i^{*} = \arg\min_{i} \{ \dots \}

缓存键设计

便利店老板最怕什么?同一种商品在货架上摆了好几个位置,顾客找不到,店员也容易补错货。CDN 的缓存系统也怕这个,而“货架编号”就是缓存键(Cache Key)。缓存键决定了两个 URL 是否被视为同一个资源:键相同则共享缓存,键不同则各存一份。

问题来了:同一个商品的 URL 常常长得不一样。比如 https://shop.com/goods?id=100&utm_source=wechat 和 https://shop.com/goods?utm_source=wechat&id=100,参数顺序不同、带了无关的追踪标记,却指向同一张商品图。如果直接拿原始 URL 当缓存键,同一张图会被存成两份甚至几十份,白白浪费边缘节点的空间,也拉低命中率。

解决办法是对 URL 做归一化处理,再计算缓存键:

缓存键的粒度也是一门学问:粒度太细(带上所有参数),命中率低;粒度太粗(忽略关键参数),不同用户拿到彼此的内容。好的缓存键设计,是在“货架不够用”和“拿错货”之间找到平衡点。

CacheKey=hash(normalize(URL))\displaystyle \text{CacheKey} = \text{hash}\big( \text{normalize}(\text{URL}) \big)
公式说明:先给商品贴上统一规格的标签,再按标签归档到货架。归一化是“去伪存真”,hash 是“对号入座”。
  1. 归一化 \(\text{normalize}(\text{URL})\)去掉 utm 等跟踪参数、固定参数顺序、统一大小写与协议,让同一资源只剩一种写法。
    URLnorm=sort(params)∖tracking\displaystyle \text{URL}_{\text{norm}} = \text{sort}(\text{params}) \setminus \text{tracking}
  2. 哈希运算 \(\text{hash}(\cdot)\)把归一化后的字符串映射为固定长度的键,便于在分布式存储中定位。
    K=SHA256(URLnorm)\displaystyle K = \text{SHA256}(\text{URL}_{\text{norm}})
  3. 键的唯一性归一化规则必须前后一致,否则同一资源在两次请求中会算出不同键,等于给同一件商品贴两个标签。
    URL1norm=URL2norm⇒K1=K2\displaystyle \text{URL}_1^{\text{norm}} = \text{URL}_2^{\text{norm}} \Rightarrow K_1 = K_2

过期策略

便利店里的鲜牛奶都有保质期,CDN 缓存也有,这个保质期叫 TTL(生存时间)。TTL 太短,店员天天催总仓补货,回源流量暴涨;TTL 太长,顾客买到过期牛奶,看到的内容是旧的。现实中的 TTL 往往由业务类型决定:版本号固定的 JS/CSS 可以设一周,实时价格接口可能只缓十几秒。

除了“保质期”,货架容量也有限,这就轮到 LRU(最久未使用)淘汰算法出场。当边缘节点存储满了,系统会优先丢掉最久没有被访问过的缓存项,就像便利店快打烊时,会把角落积灰的临期商品撤下货架,给明天可能热销的新品腾位置。

为了量化缓存策略的优劣,我们用“有效命中率”来审视:

除了被动过期,还有主动刷新机制:源站内容更新时,CDN 厂商通过 API 或消息广播主动失效指定 URL 的缓存,相当于总仓发来“召回通知”,分店立刻下架旧货。这一招让“保质期”从静态时间变成了事件驱动,兼顾了新鲜与效率。

Ehit=Habs×(1−Sratio)\displaystyle E_{\text{hit}} = H_{\text{abs}} \times (1 - S_{\text{ratio}})
公式说明:光看“命中了多少次”不够,还要看“命中的内容有多少是新鲜可用的”。
  1. 绝对命中率 \(H_{\text{abs}}\)直接统计的缓存命中比例,是监控面板上最显眼的数字。
    Habs=命中次数总请求次数\displaystyle H_{\text{abs}} = \frac{\text{命中次数}}{\text{总请求次数}}
  2. 陈旧比例 \(S_{\text{ratio}}\)返回内容已经超过业务可容忍新鲜度的概率,TTL 设得越长,这个值通常越高。
    Sratio=过期后仍被命中的次数总命中次数\displaystyle S_{\text{ratio}} = \frac{\text{过期后仍被命中的次数}}{\text{总命中次数}}
  3. 有效命中率 \(E_{\text{hit}}\)真正对用户有价值、内容又新鲜的命中比例,是调优时更该盯的指标。
    Ehit=Habs−Habs⋅Sratio\displaystyle E_{\text{hit}} = H_{\text{abs}} - H_{\text{abs}} \cdot S_{\text{ratio}}

动态内容加速

便利店不可能只卖预包装食品,顾客还想吃现场做的热三明治。三明治的原料从总仓送过来,在分店快速加工。CDN 面对动态内容也是类似思路:购物车、登录状态、实时推荐这类请求天然无法被缓存,但 CDN 依然可以为它们加速——只是优化重心从“缓存住结果”变成了“让回源旅程更快”。

动态内容加速的技术手段包括:智能路由选择更优的回源路径、TCP 连接复用(多个用户共享边缘到源站的连接)、TLS 握手优化与连接预建、HTTP/3 等新一代协议的边缘终结。用户到边缘的“最后一公里”走运营商最优路径,边缘到源站的“长途”走 CDN 专用网络,整体延迟被压到最低。

动态请求的端到端时延可以拆成三段:

动态加速的意义在于:就算不能把三明治提前做好,也能通过“预约下单、专车配送、到店即取”让顾客少等十分钟。对高并发场景而言,这十分钟的削减直接转化为转化率和用户体验。

Tdyn=Tuser-edge+Tedge-origin+Tcompute\displaystyle T_{\text{dyn}} = T_{\text{user-edge}} + T_{\text{edge-origin}} + T_{\text{compute}}
公式说明:动态请求要“到店点单、总仓备料、送回分店”。CDN 管的是第一段,优化的是第二段,第三段取决于源站自身算力。
  1. 首公里 \(T_{\text{user-edge}}\)用户到最近边缘节点的网络时延,由用户地理位置决定,CDN 已把它最小化。
    Tuser-edge=RTTuser→edge\displaystyle T_{\text{user-edge}} = \text{RTT}_{\text{user} \to \text{edge}}
  2. 长途链路 \(T_{\text{edge-origin}}\)边缘节点到源站之间的时延,动态加速通过专线、智能路由和连接复用降低它。
    Tedge-origin=RTTedge→origin−复用节省\displaystyle T_{\text{edge-origin}} = \text{RTT}_{\text{edge} \to \text{origin}} - \text{复用节省}
  3. 源站计算 \(T_{\text{compute}}\)服务器处理业务逻辑、查询数据库的时间,CDN 无法代劳,但可以靠边缘计算分担一部分。
    Tcompute=Tlogic+Tdb\displaystyle T_{\text{compute}} = T_{\text{logic}} + T_{\text{db}}

边缘网络计算

便利店的服务半径不止于卖货,它还代收快递、代缴水电费,成为社区的“服务枢纽”。CDN 的边缘节点也在经历同样的进化:从“静态缓存仓库”升级为“边缘计算平台”。最典型的场景是 WebSocket 长连接。

在线聊天、实时弹幕、股票行情推送都依赖 WebSocket 长连接。如果把长连接全部建立在源站,一个源站要维持百万级连接,内存和负载都吃不消。把 WebSocket 终结在边缘节点后,用户连接到最近的边缘节点,心跳检测、连接管理、简单消息转发都在边缘完成,只有必要的数据才回源。源站的负担一下子从“所有连接”降为“业务消息处理”。

边缘节点能承载多少长连接,可以用一个简单模型估算:

边缘计算还能把轻量业务逻辑下沉:A/B 测试分流、响应头改写、简单的请求聚合,都直接在“家门口”做完。源站专注于核心业务,边缘节点承接网络面的事务——这就是“把服务做到离用户最近的地方”的极致体现。

Cmax=BegressBsession\displaystyle C_{\text{max}} = \frac{B_{\text{egress}}}{B_{\text{session}}}
公式说明:分店门口能同时接待多少顾客,取决于门口总宽度除以每位顾客占用的空间。
  1. 单连接占用带宽 \(B_{\text{session}}\)每条 WebSocket 连接平均维持的心跳和消息流量。
    Bsession=Bheartbeat+Bavg msg\displaystyle B_{\text{session}} = B_{\text{heartbeat}} + B_{\text{avg msg}}
  2. 节点出口带宽 \(B_{\text{egress}}\)边缘节点对外提供服务的总带宽上限,是硬约束。
    Begress=带宽单价受限的固定资源\displaystyle B_{\text{egress}} = \text{带宽单价受限的固定资源}
  3. 最大连接数 \(C_{\text{max}}\)两者相除即带宽约束下的长连接容量,连接越省电,能接待的客人越多。
    Cmax=BegressBsession\displaystyle C_{\text{max}} = \frac{B_{\text{egress}}}{B_{\text{session}}}

性能调优实战

连锁便利店总部的店长每周要看三张表:卖了多少货(命中率)、补货花了多少钱(回源带宽)、有没有顾客投诉(错误率)。CDN 性能调优的逻辑一模一样。命中率是核心指标,它直接反映边缘节点“自给自足”的能力。

但调优不是先拍脑袋定个 95% 目标,而是先看懂现状。命中率的定义很直白:

提升命中率的实战手段包括:缓存键参数归一化、给版本化资源设置长 TTL、源站内容预热、主动刷新配合版本发布。回源带宽监控同样重要——即使命中率很高,某些大文件的一次回源可能就吃掉大量带宽。生产环境通常按域名、资源类型、地域三个维度拆解命中率,定位“哪家分店拖了后腿”。只有数据拆到足够细,调优才不是盲人摸象。

HitRate=HR=命中次数总请求次数\displaystyle \text{HitRate} = \frac{H}{R} = \frac{\text{命中次数}}{\text{总请求次数}}
公式说明:一百个顾客进店,九十五个直接买到想要的货,命中率就是 95%。
  1. 总请求数 \(R\)统计周期内所有到达边缘节点的 HTTP 请求数。
    R=总请求量\displaystyle R = \text{总请求量}
  2. 命中次数 \(H\)其中在边缘节点直接命中的请求数,未命中请求会产生回源。
    H=边缘直接返回的请求数\displaystyle H = \text{边缘直接返回的请求数}
  3. 命中率 \(\text{HitRate}\)两者相除得到加速效果的直接度量,但还要结合有效命中率一起看。
    HitRate=HR\displaystyle \text{HitRate} = \frac{H}{R}

生产故障排查

便利店也会遇到“水逆期”:爆款被抢空后,邻居们反复来问还有没有(缓存击穿);同一批牛奶同时过期引发退货潮(缓存雪崩);总仓换了配方,分店却还在卖旧点心(数据一致性)。生产环境里,这三个故障是 CDN 架构师最常面对的噩梦。

缓存击穿指某个热点 key 过期的瞬间,大量并发请求同时回源。好比热门商品刚下架,几十个顾客同时挤到柜台问店员,店员只能一趟趟跑总仓。解决方案是热点数据永不过期或互斥重建。缓存雪崩则指大量 key 在同一时刻集中过期,导致回源流量瞬间击穿源站。好比一整柜牛奶的保质期订在同一天,那天退货人数暴增。应对方案是给 TTL 加随机抖动,让过期时间错开。数据一致性指源站内容更新后,边缘节点还在提供旧版本,需要主动刷新和版本号机制配合解决。

回源风暴的强度可以用一个简单模型感受一下:

故障排查最怕“平时没演练,出事靠猜”。架构师应该在压测环境中人为制造缓存同时过期、热点缺失的场景,观察回源曲线是否出现尖峰,再针对性调整 TTL 抖动范围与预热策略。便利店不怕偶尔缺货,怕的是所有货架同时空空如也。

Qorigin=Qtotal×Pmiss×Noverlap\displaystyle Q_{\text{origin}} = Q_{\text{total}} \times P_{\text{miss}} \times N_{\text{overlap}}
公式说明:源站同时承受的请求量 = 总流量 × 未命中率 × 同时过期的重叠度。重叠度是雪崩的放大器。
  1. 错峰过期给相同数据的不同副本设置略有差异的 TTL,破坏同步性,是抵御雪崩的第一道防线。
    TTLi=TTLbase+rand(0,Δ)\displaystyle \text{TTL}_i = \text{TTL}_{\text{base}} + \text{rand}(0, \Delta)
  2. 热点永不过期对超高热度 key 不设过期,改为后台异步更新,避免击穿窗口。
    TTLhot=∞, 由主动刷新兜底\displaystyle \text{TTL}_{\text{hot}} = \infty, \text{ 由主动刷新兜底}
  3. 多级缓存兜底边缘未命中还有本地缓存、本地未命中再回源,层层缓冲,让洪峰逐级衰减。
    Qorigin=min(Qtotal⋅Pmiss⋅Noverlap,Qlimit)\displaystyle Q_{\text{origin}} = \text{min}(Q_{\text{total}} \cdot P_{\text{miss}} \cdot N_{\text{overlap}}, Q_{\text{limit}})

AI 应用场景

大促秒杀:CDN 全面护航电商高峰

阶段:流量预判与缓存预热阶段

解决的问题:双 11、618 这类大促开始时,图片、静态资源请求量瞬间飙到平时的数十倍。若全部打到源站,源站几秒内就会被流量打瘫。CDN 将商品主图、详情页模板、营销活动页提前预热到边缘节点,用户浏览时直接由边缘节点返回,源站只处理订单、库存等核心动态接口,流量压力呈数量级下降。

具体案例:某头部电商平台在大促前三天,运营团队通过 CDN 控制台将主会场、秒杀页全部 URL 批量提交预热任务;大促当天,静态资源命中率稳定在 97% 以上,源站带宽消耗仅为活动总带宽的 3%,下单接口平稳扛过峰值。

在线直播:边缘 WebSocket 终结低延迟信令

阶段:实时通信链路优化阶段

解决的问题:直播弹幕、连麦请求、礼物特效都是高频小消息,如果每条消息都穿到中心源站,全国用户都会感受到明显延迟。将 WebSocket 长连接终结在边缘节点后,弹幕在边缘直接聚合转发,只有需要持久化或跨房间的消息才回源,保证信令延迟在 100ms 以内,源站连接数下降 90% 以上。

具体案例:某在线教育平台高峰期有 20 万学生同时上课,聊天和答题信令通过边缘节点 WebSocket 接入,单边缘节点承载 5 万并发长连接,消息平均送达时间从原来的 380ms 降到 90ms,源站服务器从 40 台缩减到 6 台。

金融行情:动态加速守护毫秒级行情推送

阶段:低延迟传输优化阶段

解决的问题:行情报价数据不断变化,无法缓存,但对延迟极其敏感。CDN 动态加速通过智能路由、TCP 单边加速和连接复用,把用户到源站的路径优化到接近物理极限,让行情展示的刷新延迟从秒级降到毫秒级,同时避免高峰期大量连接直连源站导致的 socket 耗尽。

具体案例:某券商 APP 接入 CDN 动态加速后,行情接口 P99 延迟从 850ms 降至 210ms;在开盘瞬时并发场景下,源站连接数从 12 万降到 8 千,系统不再出现报错超时。

Python 演示

python59 行
import timeimport randomfrom collections import OrderedDict  class EdgeCache:    """模拟CDN边缘节点的缓存:LRU淘汰 + TTL过期"""     def __init__(self, capacity=50, default_ttl=10.0):        self.capacity = capacity        self.default_ttl = default_ttl        self._store = OrderedDict()        self._expire = {}        self.hit_count = 0        self.request_count = 0     def get(self, key):        self.request_count += 1        now = time.time()        if key not in self._store:            return None        if now > self._expire[key]:            del self._store[key]            del self._expire[key]            return None        self.hit_count += 1        self._store.move_to_end(key)        return self._store[key]     def put(self, key, value, ttl=None):        ttl = ttl or self.default_ttl        if key in self._store:            self._store.move_to_end(key)        self._store[key] = value        self._expire[key] = time.time() + ttl        if len(self._store) > self.capacity:            old_key, _ = self._store.popitem(last=False)            self._expire.pop(old_key, None)     def hit_rate(self):        return self.hit_count / max(self.request_count, 1)  def simulate(seed=42, size=30, capacity=50, ttl=8.0, n_requests=200):    random.seed(seed)    cache = EdgeCache(capacity, ttl)    for i in range(size):        cache.put('key_%d' % i, random.randint(1, 100), ttl)    for _ in range(n_requests):        key = 'key_%d' % random.randint(0, size)        if random.random() < 0.3:            cache.put(key, random.randint(1, 100))        cache.get(key)    print('请求次数:', cache.request_count)    print('缓存命中率: %.2f%%' % (cache.hit_rate() * 100))  if __name__ == '__main__':    simulate()
目的:用 200 行不到的模拟器复现 CDN 边缘节点的核心缓存行为——LRU 淘汰 + TTL 过期,统计不同参数下的命中率。你可以调整 capacity 和 ttl 观察命中率变化,直观感受“货架大小”与“保质期长短”的影响。
  1. self._store = OrderedDict()同时承担“缓存内容”与“访问新近度记录”两种职责,是 LRU 的基础。
  2. self._store.move_to_end(key)每次命中把键移到队尾,保证“最近用过的留下,最久没用的排到队首”。
  3. if now > self._expire[key]:命中前先检查 TTL,过期数据直接删除,相当于把过期牛奶先下架。
  4. self._store.popitem(last=False)容量超限时从队首弹出最久未使用的键,为新品腾出货架。
  5. self.hit_count += 1只有“存在且未过期”才计数为命中,过期后即使键还在也不算数。
  6. random.random() < 0.3模拟“读多写少”的业务特征,每 10 次请求约 3 次写入,让 TTL 和 LRU 同时起作用。

常见误区

误区CDN 不就是存图片、CSS 和视频这些静态文件嘛,动态接口根本走不到 CDN,一点用都没有。

正解CDN 的能力远不止静态缓存。动态内容加速通过优化边缘到源站的链路、复用 TCP 连接、减少 TLS 握手次数,能显著降低动态请求的延迟;边缘节点还能终结 WebSocket 长连接、执行轻量边缘计算。就像便利店不只是卖包装零食,还能现场做三明治、代收快递,服务边界一直在扩展。

为何常见:公开资料里 CDN 的演示案例几乎全是图片和视频,给人留下“CDN 只缓存静态资源”的深刻印象,动态加速和边缘计算的概念很少被提及。

误区改了源站内容就想让用户立刻看到,所以 TTL 设成几秒,越短越不容易让用户看到旧数据。

正解TTL 过短会让回源比例飙升,源站流量和压力暴涨,严重时直接引发缓存雪崩。新鲜与效率的平衡点不是“无限短”,而是业务容忍的“最大陈旧时间”。更优雅的做法是保持较长 TTL,配合主动刷新机制在内容变更时精准失效。

为何常见:直觉上“数据越新鲜越好”没有错,但忽略了 CDN 的核心价值正是“用可容忍的陈旧换取延迟和压力的双重下降”。

误区看到命中率 95% 就觉得万事大吉,CDN 一定调得很好了。

正解命中率高还要看“有效命中率”——大量命中可能是 TTL 即将过期的旧内容,用户看到的是过期数据。同时命中率高不代表回源链路最优,动态请求、大文件回源带宽、边缘节点间的负载均衡同样影响体验。命中的“量”和内容的“鲜”要一起看。

为何常见:监控面板上命中率最显眼,而且“高命中率 = 缓存效率高”在单机缓存场景完全成立,于是被错误套用到 CDN 全链路。

误区域名加了解析、配置上了线,流量应该立刻全部走 CDN,马上看到命中率飙升。

正解DNS 的 TTL 会让旧解析记录在用户本地缓存残留几个小时;边缘节点冷启动时货架空荡荡,需要预热才能接近高命中率。真实上线流程要留出“生效等待 + 缓存预热”的时间窗口,并分地域灰度验证。

为何常见:开发环境修改配置秒级生效,让人误以为生产环境的 DNS 层、边缘节点分布也是即时响应的,忽略了分布式系统的传播延迟。

误区动态接口每次返回结果都不一样,缓存没用,所以 CDN 对动态内容毫无价值。

正解动态加速的切入点不是“缓存住结果”,而是优化请求旅程:缩短边缘到源站的网络路径、复用底层连接、减少 TLS 握手次数、预连接源站。它减少的是“在路上”的时间,而不是“在店里”的等待,非常适合接口延迟敏感的实时业务。

为何常见:很多人把 CDN 与缓存画等号,而缓存只能服务于可复用内容,于是想当然推出“动态内容无解”的结论,其实没看到链路优化这一层。

面试题

Q1. CDN 的核心作用是什么?

单选题 · easy

  • A.将内容推近用户,降低访问延迟← 正确答案
  • B.提高源站 CPU 的计算速度
  • C.替代数据库存储用户全部数据
  • D.加密所有网络传输的报文

答案:A。CDN 通过把静态资源部署到离用户更近的边缘节点,让用户“楼下取货”而不是“进城采购”,核心收益就是降低访问延迟。它不负责提升源站算力,也不替代数据库,加密只是一项附加能力而非核心职责。

Q2. 用户在边缘节点直接命中缓存时,以下哪种内容最典型?

单选题 · easy

  • A.图片、CSS、JavaScript 文件← 正确答案
  • B.用户登录态的实时校验结果
  • C.个人私密聊天记录
  • D.数据库写入成功的确认消息

答案:A。图片、CSS、JS 等静态资源几乎不变,最适合缓存。登录态、聊天记录、写入确认都强依赖用户维度且实时性高,直接缓存会串号或泄露隐私。

Q3. GSLB 调度器通常会依据什么信息选择就近节点?

单选题 · easy

  • A.用户本地 DNS 的出口 IP← 正确答案
  • B.用户手机的剩余电量
  • C.源站磁盘的剩余空间
  • D.边缘节点的 CPU 是几核

答案:A。GSLB 根据本地 DNS 的出口 IP 推断用户地理位置和运营商,再结合节点负载返回最优 IP。手机电量、磁盘空间、CPU 核数都不是调度决策的依据。

Q4. 缓存键做 URL 归一化主要解决什么问题?

单选题 · mid

  • A.同一资源因参数顺序或跟踪标记被重复缓存← 正确答案
  • B.缓存数据在传输途中被恶意篡改
  • C.边缘节点磁盘空间无法加密
  • D.源站数据库出现死锁

答案:A。?id=1&utm=a 与 ?utm=a&id=1 指向同一资源,若直接做缓存键会存两份。归一化去掉跟踪参数、固定顺序,让同一商品只占一个货架位,提升命中率。与篡改、加密、死锁无关。

Q5. TTL 设置过短会带来什么主要风险?

单选题 · mid

  • A.回源请求增多,源站压力变大← 正确答案
  • B.用户永远只能看到最新内容
  • C.边缘节点会自动扩容磁盘空间
  • D.缓存命中率上升但带宽下降

答案:A。TTL 是保质期,太短意味着频繁过期,货架经常空,大量请求只能回源补货,源站流量压力急剧上升,甚至引发雪崩。它不会提升命中率,与磁盘扩容无关。

Q6. 动态内容加速与静态缓存的最大区别是什么?

单选题 · mid

  • A.动态请求仍需回源,但优化了回源链路← 正确答案
  • B.动态请求完全不经过任何 CDN 节点
  • C.动态请求使用文件系统存储响应
  • D.动态请求无法被任何代理处理

答案:A。动态内容无法缓存,但 CDN 可通过智能路由、连接复用、TLS 优化缩短边缘到源站的“长途”,本质是让“点单-备料-配送”更快,而不是提前囤货。

Q7. WebSocket 长连接放到边缘节点终结的主要好处是什么?

单选题 · mid

  • A.用户连接最近的边缘节点,降低信令时延← 正确答案
  • B.边缘节点可以修改用户浏览器的协议
  • C.源站从此不需要存储任何数据
  • D.浏览器会自动降低视频清晰度

答案:A。长连接终结在边缘后,心跳、连接管理、消息转发在本地完成,用户信令不用穿城到源站,时延大幅降低,源站连接数也骤减。它不修改浏览器协议,也不替代数据存储。

Q8. 下列哪些手段能有效提升 CDN 缓存命中率?

多选题 · mid

  • A.缓存键参数归一化处理← 正确答案
  • B.合理设置 TTL 并主动刷新← 正确答案
  • C.强制禁用浏览器的缓存策略
  • D.按业务内容分组管理资源← 正确答案

答案:ABD。参数归一化让同一资源只存一份,合理 TTL 加主动刷新减少过早失效,按业务分组有助于差异化配置缓存策略——这三者都直接提升命中率。禁用浏览器缓存只会让请求全部打到 CDN,并不提升 CDN 自身命中率。

Q9. 缓存雪崩的典型应对措施有哪些?

多选题 · hard

  • A.TTL 增加随机抖动错峰过期← 正确答案
  • B.设置热点数据永不过期← 正确答案
  • C.清空所有边缘节点缓存
  • D.预加热加多级缓存兜底← 正确答案

答案:ABD。TTL 抖动让过期时间错开,避免同时失效;热点永不过期消除击穿窗口;预加热加多级缓存让洪峰逐级衰减,三层措施共同抑制回源风暴。清空所有缓存反而制造一次全局雪崩。

Q10. GSLB 调度时通常参考哪些因素选择边缘节点?

多选题 · extreme

  • A.用户地理位置和运营商← 正确答案
  • B.边缘节点实时负载情况← 正确答案
  • C.源站数据库的字符集配置
  • D.网络链路的实时质量状况← 正确答案

答案:ABD。GSLB 是“导航系统”,既要看用户位置和运营商(决定基础距离),也要看各节点当前负载(避免堵车)和链路质量(避开故障线路)。源站数据库字符集属于业务层配置,与边缘节点调度决策无关。