← 返回题目列表

SSR 页面如何做缓存?

高频 中等 第 7 / 25 题 更新于 2026/07/28
SSR缓存CDN性能优化

简化版

SSR 缓存可以分页面缓存、接口缓存、组件片段缓存和 CDN 缓存。公共页面适合缓存,用户个性化页面要谨慎。设计时要考虑缓存 key、过期时间、失效策略、用户隔离和数据实时性。

详细版

SSR 每次请求都渲染会增加服务端压力。缓存可以降低响应时间和机器成本。

常见缓存:

  • CDN 缓存 HTML。
  • 服务端页面缓存。
  • 接口数据缓存。
  • 组件片段缓存。
  • 请求级缓存,避免同次渲染重复请求。

注意点:

  • 用户私有内容不能被公共缓存。
  • 缓存 key 要包含语言、地区、设备、登录态等影响因素。
  • 新闻、商品库存等数据要考虑实时性。
  • 发布后要能失效缓存。

完整版教学

一、SSR 为什么需要缓存

SSR 每个请求都可能执行路由匹配、数据请求、组件渲染和 HTML 拼接。高流量下,如果没有缓存,服务器压力会很大,TTFB 也可能升高。

缓存能把重复计算和重复请求省掉。

二、页面缓存

如果页面对所有用户都一样,比如文章详情、商品基础信息、营销页,可以缓存完整 HTML。

缓存位置可以在 CDN、网关或 Node 服务内。CDN 缓存效果最好,因为请求不必打到源站。

但如果页面包含用户昵称、购物车数量等个性化内容,就不能简单全页面公共缓存。

三、接口缓存和请求级缓存

接口缓存可以减少后端压力。请求级缓存用于同一次 SSR 中避免重复请求同一个数据。

例如页面多个组件都需要用户信息,同一次请求内应该复用结果,而不是请求三次。

四、面试追问与工程落地

面试官可能问:“SSR 缓存最怕什么问题?”

最怕缓存串用户。比如把 A 用户的个人页面缓存成公共 HTML,B 用户访问时看到 A 的信息。这是严重安全事故。

工程中所有缓存都要明确是公共缓存还是私有缓存,缓存 key 和响应头要严格设计。

五、四层缓存和 key 推导

SSR 常同时存在请求内 memo、数据缓存、HTML 页面缓存和 CDN。每层复用范围不同:

层次生命周期典型 key最大风险
请求 memo单次 SSR函数 + 参数请求结束未释放
数据缓存跨请求数据 id + 版本/租户陈旧或越权
HTML 缓存跨请求URL + 页面维度串用户
CDN跨地域用户host/path/query/Vary大范围泄露或旧页

假设公开文章渲染需 80ms,缓存命中需 5ms,1000 QPS 时可节省约 75 CPU-ms/请求,理论每秒少约 75 个 CPU 核心的渲染工作量;实际还要扣除缓存读写和序列化成本。

缓存 key 必须由所有影响输出的输入推导;漏一个维度会返回错误内容,多一个高基数维度又会让命中率崩掉。

六、响应头、失效和防击穿

公共 HTML 可配置共享缓存,私有页面应 privateno-store,并谨慎处理 Set-Cookie。一旦响应随 Cookie 变化,简单 CDN 公共缓存非常危险;不要用 Vary: Cookie 掩盖无界 Cookie 组合造成的缓存碎片。

Cache-Control: public, s-maxage=60, stale-while-revalidate=300
Vary: Accept-Encoding, Accept-Language

60 秒后缓存可在后台更新期间继续提供最多 300 秒旧内容,但支持和具体语义取决于缓存层。更新必须 single-flight;100 个请求同时过期时只允许一个回源渲染,其他读旧值或等待,避免击穿。

失效采用 TTL + 事件 tag。商品名称修改时失效商品数据与相关页面;部署新模板时还应让 HTML key 包含构建版本,避免新旧代码复用不兼容的旧片段。监控命中率、陈旧时间、回源耗时和 key 基数。

对于多租户系统,tenantId 应从已验证身份推导并进入缓存 key,不能直接相信 query 参数。缓存值也应携带 schema/build 版本,读取到不兼容版本时安全 miss,而不是强行反序列化。

高敏感页面可在自动化测试中断言 Cache-Control: private, no-store,防止后续中间件重构意外放宽。

清除缓存时要覆盖页面、数据和 CDN 等关联层级,否则只删一层仍可能继续返回旧内容。

七、常见误区与追问

  • 误区:SSR 页面只按 URL 缓存就够了。 语言、地区、登录态、实验和设备可能改变输出。
  • 误区:给个性化 HTML 加 Vary: Cookie 就一定安全高效。 Cookie 高基数会碎片化缓存,错误 key 仍可能串用户。
  • 误区:缓存过期时所有请求都去重建最及时。 会造成击穿,应 single-flight 并考虑 stale 服务。
  • 追问:请求 memo 为什么不等于数据缓存? 它只在一次渲染内去重,不跨用户也无需全局失效。
  • 追问:什么时候可以 CDN 缓存 HTML? 输出公开且所有 key 维度明确、无用户私密内容时。
  • 追问:模板发布为何要影响缓存 key? 同一数据在新旧模板下 HTML 不同,版本隔离可避免结构不兼容。
  • 追问:怎样发现缓存串用户? 用多账户并发测试、响应标记和审计日志验证 key 与输出身份,且禁止敏感字段进公共层。

八、加强记忆

  1. 先分层:请求 memo、数据、HTML、CDN 四层范围不同。
  2. 再分类:公共内容可跨用户复用,私有内容默认不进公共缓存。
  3. 推导 key:URL 加语言、地区、版本等真正影响输出的有限维度。
  4. 设计失效:TTL 控陈旧,事件/tag 控及时更新,版本 key 控部署。
  5. 保护回源:single-flight、stale 和限流防止过期击穿。
  6. 持续监控:命中率、key 基数、陈旧度、回源耗时和身份隔离一起看。