个性化与缓存 · 每人不同的页面怎么缓存

「你好,张三」这种每人不同的页面,天生和共享缓存(CDN)水火不容——缓存了发给别人就是灾难。可我们又想要 CDN 的速度。这一章给出破局的整套工具:拆分静态壳与动态洞、按人群分段、边缘个性化、部分预渲染。这是缓存的压轴。

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

个性化与缓存 · 每人不同的页面怎么缓存

缓存这一站,压轴的是最硬的一块骨头:个性化内容。

矛盾很尖锐。HTTP 缓存那章 划过一条红线:个性化内容必须 private,绝不能进共享缓存——否则 CDN 把「你好,张三」缓存下来发给李四,就是信息泄露。可另一边,我们又眼馋 CDN 的速度和扛量。「每人不同」和「大家共享一份缓存」,天生对立。 这一章讲怎么破。

破局的总纲:把「共享的」和「私有的」分开

所有解法都源自同一个洞见:

一个「个性化页面」,极少是 100% 个性化的。 它通常是一大片对所有人相同的内容(布局、文章正文、商品信息、推荐榜)+ 一小撮每人不同的东西(名字、头像、购物车数量、是否已登录)。

既然如此,就别把整页当成一个不可分的整体去纠结「能不能缓存」。把共享的部分和私有的部分拆开,各用各的策略:共享的大片,尽情用 CDN 缓存;私有的一小撮,单独实时取。 下面几种方案,都是这个总纲的不同实现。

图表加载中…

方案一:静态壳 + 客户端补洞

最经典、最好落地:把共享外壳做成可缓存的静态页(CDN 秒回),个性化的小洞留空,等页面到了浏览器再用一个客户端请求填上。

  • CDN 缓存并秒回那片共享外壳——首屏飞快、SEO 完整(正文都在)。
  • 页面加载后,一个轻量的客户端请求(/api/me)拉回「张三、购物车 3 件」,填进预留的洞里。

代价:个性化的小洞有个「先空着、后填上」的短暂闪现。但用极小的代价,换回了整页的 CDN 缓存——绝大多数内容站的登录态导航栏就是这么做的。

方案二:按「人群」分段,而不是按人

有时你不想要客户端补洞的闪现,想让服务端直接发出带个性化的完整 HTML,又还能缓存。诀窍:别按「每个用户」缓存(那是无穷多份,等于没缓存),按「人群段(segment)」缓存。

关键是缓存键的「基数(cardinality)」。 按 user_id 做缓存键 → 一百万用户一百万份缓存,命中率趋零。但如果你的个性化其实只分几类人群——「登录 vs 未登录」「中国 vs 海外」「A/B 实验的 A 组 vs B 组」——那就按这个低基数的维度缓存:整个站可能只有「登录版」和「未登录版」两份缓存,依然高命中。用 Vary 或 CDN 的缓存键配置,按这个粗粒度维度分段即可。个性化 ≠ 一定要精确到人;能降到「按段」,就还能缓存。

典型:未登录访客全看同一份缓存页(占流量大头,缓存价值最高);登录用户再走个性化路径。仅此一分,就把大部分流量挡在了缓存层。

方案三:边缘个性化

边缘渲染那章 埋过一个伏笔,这里收:在边缘节点上,缓存共享外壳,再就地把个性化的小块注入进去。

边缘节点离用户近、又能读到请求里的 Cookie,于是它可以:从边缘缓存取出共享外壳(~0 延迟)→ 从 Cookie 认出用户 / 人群 → 把「你好,张三」就地拼进去 → 发出。共享部分吃缓存,个性化部分在离用户最近处轻量拼装,兼得速度与个性化。这类「边缘拼装」的老祖宗是 ESI(Edge Side Includes),如今被各家边缘中间件现代化地重新实现。

方案四:部分预渲染(PPR)

框架层最新的答案,是把「静态壳 + 动态洞」做成一次请求内的原生能力——部分预渲染(Partial Prerendering,PPR):

  • 构建时就把共享外壳预渲染成静态(像 SSG,CDN 可缓存)。
  • 页面里用 <Suspense> 圈出的个性化小洞,则在每次请求时流式地填进那个静态壳里——在同一个 HTTP 响应内完成。

于是用户一个请求就拿到:静态壳瞬间到达(缓存级速度),个性化的洞随后流式补上(实时),没有方案一那种「到浏览器再发第二个请求」的往返。这是「共享缓存」和「实时个性化」一次漂亮的融合,Next.js 等正在推进它落地。

一条必须焊死的纪律

不管用哪个方案,有一条铁律违反即出事:

绝不让任何一个用户的私有数据,污染共享缓存。 具体到操作:① 会进共享缓存(public)的响应,绝不能带 Set-Cookie,也绝不能在 HTML 里嵌入任何用户私有数据;② 个性化响应一律 private 或 no-store;③ 拆分时想清楚每一块的「共享 / 私有」归属,别让个性化数据混进「共享外壳」里被缓存走。http 缓存那章 说的「张三的页面被发给李四」,几乎都源于这条纪律的破防。 个性化缓存的所有精巧,都建立在「共享的归共享、私有的归私有」这条界线绝不含糊之上。

小结与下一章

个性化和共享缓存的对立,靠一个总纲破解:拆开「共享的大片」和「私有的一小撮」,各用各的策略。 落地有四招——客户端补洞(最好上手)、按人群分段(降基数换命中)、边缘个性化(就近拼装)、部分预渲染(一次请求融合)。而贯穿始终的铁律是:私有数据绝不能污染共享缓存。

缓存这一整站(八章)到此讲完——从 HTTP 头到 CDN、SWR、ISR、数据缓存、失效、个性化。你已经有了让 SSR「扛得住」的整套武器。最后一站转向实战:这些东西上了生产,该量什么指标、怎么排查。👉 量化与排查:TTFB、LCP 与缓存命中率。

参考文献

本页目录