什么是缓存?面向应用构建者的通俗指南
缓存是指保留一份现成的副本,这份内容本身获取起来很慢或成本很高,因此下次请求时可以直接从这份副本快速作出响应。保存下来的副本称为缓存(cache)。例如,浏览器会缓存图片,使你第二次访问网站时加载得更快;服务器会缓存慢速数据库查询的结果,这样就不必为每位访客都执行一次查询。
缓存能让应用运行得更快,成本也更低。它的一个主要权衡是:副本可能会过时。
用 AI 构建应用时为什么缓存很重要
在 AI 构建的应用中,你会在三种情况下遇到缓存:
- “我更新了应用,但仍然看到旧版本。” 这是最常见的缓存情形,通常并无大碍——你的浏览器或 CDN 正在显示保存的副本。
- 速度。 如果某个页面因为对每位访客都要重新计算相同的数字而变慢,那么缓存计算结果可以让它几乎瞬间打开。
- 成本。 许多 AI 构建工具和主机会对计算资源、数据库时长和外部 API 调用收费。如果一千位访客都触发了同一个昂贵的请求,缓存可以让你只为它付一次费用。
了解基本知识后,你就能在有帮助的地方主动要求使用缓存,也能在缓存导致某些异常现象时及时发现问题所在。
一个日常类比
想象一家繁忙咖啡馆的厨房。
每天早上,咖啡师可以在顾客点单时,现磨咖啡豆再冲泡每一杯咖啡,但这样很慢。于是他们会把一壶滤泡咖啡提前放在保温板上。大多数顾客几秒钟就能拿到咖啡——这就是缓存命中(cache hit)。当这壶咖啡卖完,就重新冲泡一壶——这就是缓存未命中(cache miss)。
但咖啡放太久会变质,所以咖啡馆规定:超过 30 分钟的咖啡壶一律倒掉。这条规则就是缓存的过期时间。没有人会整天都用同一壶咖啡,也没有人会提前泡好某位顾客特制的、加了燕麦奶和三勺糖的咖啡——有些东西根本不应该被缓存。
缓存存放在哪里
一次页面加载可能会经过多层缓存,从离用户最近到最远依次排列:
| 缓存 | 位置 | 通常存储的内容 | 示例 |
|---|---|---|---|
| 浏览器缓存 | 在访问者的设备上 | 图片、样式表、脚本、字体 | 你的 Logo 在第二个页面中即时加载 |
| CDN 缓存 | 分布在世界各地、靠近访问者的服务器 | 静态文件,有时包括整个页面 | 东京的访问者从附近的服务器获取文件,而不是从你的源站获取 |
| 应用缓存 | 位于服务器上或其旁边,通常在内存或 Redis 中 | 慢速查询或外部 API 调用的结果 | 今日汇率,每小时获取一次 |
| 数据库缓存 | 位于数据库内部 | 最近使用过的数据和查询计划 | 热门数据行保留在快速内存中 |
CDN(内容分发网络)本质上是一个面向全球、专门缓存你网站文件的缓存网络。
缓存如何决定保留什么
每一层缓存都必须回答同样的几个问题:
- **什么可以缓存?**公开的共享数据(如商品图片、博客文章)——可以。私人数据(如用户的账户页面、他们的消息)——绝不能放在共享缓存中。
- **缓存多久?**这就是 TTL(存活时间)。Logo 可能缓存一年,而库存数量可能只缓存 30 秒。
- 如何更新?要么副本过期后重新获取,要么在数据变化时由应用主动删除副本——这称为失效(invalidation)。
对于网站而言,服务器通过 Cache-Control 响应头告诉浏览器和 CDN 如何缓存每个文件。例如,Cache-Control: max-age=3600 表示“这份副本可以重复使用一小时”。
现代构建工具通过**缓存破坏(cache busting)**解决了静态文件中最困难的部分:每当文件发生变化时,它都会被赋予一个带指纹的新名称,例如 app.3f9a2c.js。浏览器可以长期缓存旧名称,因为新版本的文件名本身就不同。
实例演示:一个商品目录
假设你经营一家小型网店。首页显示 50 件商品,包括来自数据库的价格和库存数量,还有一个“热门”列表,需要对所有订单进行一次很慢的计算。
- 图片和脚本由浏览器和 CDN 长时间缓存。每次构建时,有变化的文件都会获得新名称,因此更新依然会显示出来。
- 热门列表每 10 分钟计算一次,并存入应用缓存。这 10 分钟内的每位访客都能立即获得保存好的结果。
- 价格只缓存很短的时间,并且每当你编辑商品时都会清除缓存,因此顾客不会长时间看到旧价格。
- 结账时的库存绝不缓存。当有人点击“购买”时,应用会查询真实数据库,因此不会卖出刚刚售罄的商品。
- 购物车和账户页面绝不存放在共享缓存中,因为它们属于个人信息。
结果是:首页快速打开,数据库的工作量大幅减少,而且与金钱或隐私相关的内容绝不会过时。
关键术语
| 术语 | 含义 |
|---|---|
| 缓存命中 / 未命中(Cache hit / miss) | 数据在缓存中找到 / 必须从源头获取。 |
| TTL(存活时间,time to live) | 缓存副本被视为新鲜的时长。 |
| 过期数据(Stale data) | 已经过时的缓存副本。 |
| 失效(Invalidation) | 因原始数据已更改而主动删除缓存副本。 |
| 缓存破坏(Cache busting) | 文件变化时更改其名称或 URL,使缓存获取新版本。 |
| Cache-Control | 告诉浏览器和 CDN 如何缓存响应的 HTTP 响应头。 |
| 强制刷新(Hard refresh) | 重新加载页面,并让浏览器忽略其缓存。 |
| Redis | 一种流行的内存数据存储,常被用作应用缓存。 |
常见误解
- **“缓存总是有益的。”**缓存了错误的内容会引发真正的错误:旧价格、新文章不显示,或者最糟糕的情况——某位用户的私人页面被展示给另一位用户。缓存要有明确的规划。
- **“如果看到旧版本,说明我的更新失败了。”**通常并非如此。在认为出了问题之前,先尝试强制刷新(Ctrl+Shift+R,或 Mac 上的 Cmd+Shift+R)或使用无痕窗口。
- **“缓存能解决应用慢的问题。”**它只是对重复请求掩盖了慢的问题。第一次请求仍然很慢;如果根本问题是缺少数据库索引,也需要一并修复。
- **“应该把所有内容尽可能长时间地缓存。”**较长的缓存时间适用于内容变化时会获得新名称的文件。对于 HTML 页面和数据,较短的时间更安全。
- **“清除我的缓存就能为所有人解决问题。”**它只清除你自己浏览器中的缓存。访客的浏览器和 CDN 缓存仍然保留着各自的副本。
向你的 AI 构建工具提出的要求
- “这个应用的哪些部分运行缓慢,哪些部分可以安全地缓存?”
- “将[热门列表 / API 结果]缓存 [N] 分钟,并在底层数据变化时清除该缓存。”
- “确保任何包含个人或账户数据的页面都不会被 CDN 或共享缓存缓存。”
- “为带指纹的静态文件设置较长的缓存时间,为 HTML 设置较短的缓存时间。”
- “缓存来自[外部 API]的响应,这样我们不必在每次加载页面时都调用它——并告诉我这些数据可能会过时到什么程度。”
- “发布后我看到的是旧版本。这是我的浏览器缓存,还是有内容没有部署?”
Mythex 中的缓存
向 Mythex 应用发布更新后,文档提到 CDN 缓存可能会短暂滞后,对公开网址进行强制刷新即可看到新版本——参见如何发布。托管限制页面还建议缓存静态资源,因为托管、数据库时长和带宽都从你的积分余额中扣费。除此之外,例如缓存查询结果或 API 响应,则需要你请智能体将其构建到应用中。
延伸阅读:什么是 CDN、如何让你的网站更快,以及什么是速率限制。
常见问题
用简单的话说,什么是缓存?
缓存是指把一些获取起来很慢或成本很高的内容保存一份副本,下次需要时就可以直接从保存的副本快速提供。浏览器、CDN、服务器和数据库都使用缓存,让应用运行得更快、成本更低。
我更新了网站,为什么还能看到旧版本?
你的浏览器或 CDN 很可能仍在提供旧文件的缓存副本。通常执行一次强制刷新(Windows 上为 Ctrl+Shift+R,Mac 上为 Cmd+Shift+R)即可解决。对于访问者来说,设计良好的网站会为更新后的文件赋予新的文件名,使缓存自动获取新版本。
清除缓存会做什么?
清除浏览器缓存会删除浏览器此前保存的文件和页面副本,因此下次会重新下载所有内容。它可以修复显示异常或内容过时的页面,但之后首次加载时页面会稍慢一些。
缓存会造成问题吗?
会的。主要风险是提供过期数据,例如旧价格、过时的库存数量;更糟的是,把某个用户的私人页面缓存下来,然后展示给其他人。良好的缓存规则会明确哪些内容可以缓存、缓存多长时间,并且绝不在共享缓存中缓存个人数据。