为什么 SSR 必须缓存 · 渲染一次,服务千次

SSR 每个请求都要现算 HTML——这很贵。缓存的本质,是让「渲染一次的结果」被复用千次万次。这一章讲清缓存为何是 SSR 的命门、缓存的分层结构,以及那条贯穿始终的「新鲜度 vs 扛量」权衡。

作者 David更新于 第 8 篇(共 17 篇)

为什么 SSR 必须缓存 · 渲染一次,服务千次

我们正式进入本专栏的重点。开篇先把最重要的直觉钉牢:

SSR 的本质是「每请求现算」,而缓存的本质是「算一次、用很多次」。 没有缓存的 SSR,几乎无法上规模。

SSR 那章 说过:每一个请求,服务器都要查库、调 API、把组件渲染成 HTML 字符串。假设渲染一个页面要 50ms CPU——一个请求还好,可当这个页面每秒被访问 2000 次,服务器每秒就要花 100 秒的 CPU 去渲染。渲染开销随流量线性增长,服务器很快就被自己压垮。

缓存改变了这个算式:把渲染好的结果存起来,后续请求直接拿现成的,根本不再触发渲染。 一次渲染的成果,可以服务成千上万个请求。这就是缓存对 SSR 的意义——它不是「优化项」,而是让 SSR 在生产环境可用的前提。

命中与未命中:一切的分水岭

缓存世界里最重要的两个词:

  • 命中(hit):请求要的东西缓存里有,直接返回。快、几乎零成本。
  • 未命中(miss):缓存里没有,只能老老实实去现算一遍(触发完整 SSR),再把结果存进缓存。慢、贵。

于是缓存的全部目标,就是尽可能提高命中率(hit ratio)。命中率 99% 意味着 100 个请求里只有 1 个真的触发了渲染,其余 99 个都是从缓存里秒回的——服务器的渲染压力直接降到 1%。命中率从 90% 提到 99%,不是「好一点」,是渲染负载降为原来的十分之一。

缓存是分层的

缓存不是一个东西,而是一串关卡。一个请求从用户出发,会依次经过多层缓存,在任何一层命中,就不必再往后走——尤其是不必走到最贵的那一步:源站现算。

图表加载中…
  • ① 浏览器缓存:用户自己电脑上的缓存。命中的话,请求根本没离开设备,最快。
  • ② CDN / 边缘缓存:离用户最近的 CDN 节点。命中的话,请求没到你的服务器——这是保护源站最关键的一层,后面专门讲。
  • ③ 应用 / 数据缓存:你服务器内部的缓存(Redis、内存、框架的数据缓存)。渲染时要的数据命中这里,就省掉查库 / 调 API。
  • ④ 源站现算:全都没命中,才真正跑一次完整 SSR。这是你最想避免触发的一步。

记住这个「关卡」心智:每往后一层,成本高一个数量级。 浏览器命中 ≈ 免费;CDN 命中 ≈ 一次就近网络读取;应用缓存命中 ≈ 省掉数据库;源站现算 ≈ 全套开销。缓存优化的艺术,就是让尽可能多的请求在尽可能靠前的关卡就被拦下。 后面几章会逐层展开:HTTP 头(浏览器)、CDN(边缘)、数据缓存(应用)。

缓存缓存的到底是什么

「缓存」在 SSR 语境里,其实指两类不同的东西,别混:

  • 整页 HTML 缓存(full-page / route cache):把渲染好的整份 HTML 存起来。命中时直接吐 HTML,连渲染都省了。最省,但只适合「对所有人一样」的页面。
  • 数据缓存(data cache):缓存的不是 HTML,而是渲染时要用的数据(某个 API 的返回、某次查询的结果)。命中时仍要渲染,但省掉了取数。适合「HTML 因人而异、但底层数据可共享」的场景。

这两类对应不同的层、解决不同的问题,后面都有专章。现在你只要知道:「缓存 HTML」和「缓存数据」是两把不同的刀。

绕不开的权衡:新鲜度 vs 扛量

渲染光谱那章 提过的核心矛盾,在缓存这里变成了最日常的决策:

缓存的每一个好处,都是用「一点点不新鲜」换来的。

你把一份渲染结果缓存 60 秒——这 60 秒内,哪怕源数据变了,用户看到的还是旧的。你换来了这 60 秒内近乎无限的扛量(全走缓存),代价是最多 60 秒的陈旧。缓存时间(TTL)越长,越省、越能扛,但越可能给用户看旧数据;越短,越新鲜,但命中率越低、越常触发昂贵的渲染。

缓存的全部功夫,就是在「能容忍多旧」和「想省多少」之间,为每一类内容找到那个甜点。 一个每周更新的博客,缓存一小时都嫌短;一个秒级变动的股价,缓存 5 秒都嫌长。没有万能 TTL,只有「这个内容能容忍多旧」。

小结与下一章

SSR 每请求现算、开销随流量线性涨,缓存用「算一次、用很多次」破了这个局。缓存是分层的关卡(浏览器 → CDN → 应用 → 源站),越靠前越省;缓存的对象分整页 HTML 和数据两类;而所有缓存决策都逃不开新鲜度 vs 扛量的权衡。

理解了「为什么」,接下来逐层攻破「怎么做」。第一层、也是一切缓存的基石,是 HTTP 协议本身的缓存机制——服务器靠一个 Cache-Control 响应头,就能指挥浏览器和 CDN 怎么缓存。下一章从零讲透它。👉 HTTP 缓存基石:Cache-Control 全家桶。

参考文献

本页目录