第1章 离线缓存核心概念
离线缓存是REST API客户端在失去网络连接后,仍能从本地存储中读取先前的响应,并在恢复网络时与服务器同步的技术。理解缓存命中、失效、离线模式、一致性(Coherence)以及HTTP Cache-Control指令,是构建可靠离线缓存方案的基石。本章逐一剖析这些概念,并给出可操作的影响与配置示例。
1.1 缓存命中与失效
| 概念 | 定义 | 客户端表现 | 代价 |
|---|---|---|---|
| 缓存命中 | 请求的资源在本地缓存中存在且未过期 | 立即返回本地数据,无网络延迟 | 占用本地存储空间 |
| 缓存失效 | 缓存数据因过期、被主动清除或服务器声明不可用 | 需要发起网络请求刷新资源 | 网络延迟、流量损耗 |
实践建议:合理设置资源优先级——频繁变动的API使用较短的过期时间(如5分钟),静态资源(图标、版本号)使用较长过期时间(如1天),以减少不必要的缓存失效请求。
1.2 离线模式与一致性(Coherence)
离线模式指客户端完全脱离网络后,仅依靠缓存中的数据提供服务。此时,若缓存中的数据在服务器端已更新,则会出现数据不一致问题。一致性(Coherence)即保证离线期间本地缓存与远程服务器的最终数据一致。常见的解决思路包括:
- 写回策略(Write-Back):离线时先将修改保存在本地队列,恢复网络后批量同步。
- 版本向量(Version Vector):每个资源附带版本戳,同步时比较版本差异解决冲突。
- 到期强制刷新:离线时间过长时,强制清除过期缓存,要求用户重新联网加载。
1.3 Cache-Control 指令
HTTP Cache-Control 响应头是服务器控制缓存行为的主要手段。以下指令直接影响离线缓存的命中/失效/一致性策略:
| 指令 | 含义 | 对离线缓存的影响 |
|---|---|---|
max-age=seconds | 资源从生成起有效秒数 | 离线期间若在有效期内,可安全使用;过期后视为失效 |
no-cache | 每次使用前需向服务器验证是否更新 | 离线时无法验证,缓存不可用(退化至无缓存) |
no-store | 禁止任何形式的缓存 | 离线缓存无法保存该资源 |
must-revalidate | 过期后必须与服务器重新验证 | 离线时若网络不可达,即使缓存存在也不允许使用(一致性要求高) |
stale-while-revalidate | 过期后允许使用旧缓存,同时在后台异步更新 | 离线期间若更新请求失败,仍可暂时使用旧数据,提升可用性 |
常见错误:为追求高命中率,将静态API的
max-age 设置得极大(例如30天)。一旦服务器资源变更,客户端将长期使用错误数据,且离线模式下的冲突更难解决。建议结合 immutable 或 stale-while-revalidate 指令平衡。
1.4 核心概念关系图
下图展示了离线缓存各核心概念之间的逻辑关系与数据流向:
1.5 代码示例:服务端设置 Cache-Control
下面以 Node.js + Express 为例,演示如何为 API 响应设置 Cache-Control 指令,使其支持离线缓存(max-age + stale-while-revalidate):
const express = require('express');
const app = express();
app.get('/api/catalog', (req, res) => {
// 假设从数据库获取商品列表
const data = { items: [...] };
// 允许缓存 5 分钟,过期后仍可使用旧数据 60 秒,同时后台更新
res.set('Cache-Control', 'public, max-age=300, stale-while-revalidate=60');
res.json(data);
});
app.listen(3000, () => console.log('API running on port 3000'));
1.6 调试与常见错误
- 缓存未生效:检查服务端是否正确设置了
Cache-Control头,以及客户端(如浏览器、Service Worker)是否拦截了缓存策略。 - 离线数据过老:如果使用
stale-while-revalidate但未设置stale-if-error,离线时网络不可达将无法获得任何数据。 - 一致性冲突:不同客户端同时离线修改同一资源,恢复网络后同步时出现版本冲突。务必引入版本号或时间戳机制。
1.7 性能与稳定性优化
优化要点:
- 对读多写少的 API 使用较长的
max-age并配合must-revalidate降低服务器压力。 - 结合 Service Worker 实现离线缓存策略(例如“缓存优先,网络回退”),在用户无感的情况下提升首屏加载速度。
- 监控缓存命中率与失效比例,动态调整过期时间——命中率长期低于 30% 的 API 应考虑缩短过期或移除缓存。