缓存策略
规则
- 在每一层进行缓存:浏览器(Cache-Control)、CDN(边缘)、应用层(Redis)、数据库(查询缓存)
- 对可以稍微过期的内容使用
stale-while-revalidate —— 快速响应,后台刷新
- 缓存头:对哈希后的静态资源使用
public, max-age=31536000, immutable;对动态页面使用 public, s-maxage=60, stale-while-revalidate=300
- Redis 缓存:序列化为 JSON,为每个键设置 TTL,使用命名空间键(
cache:users:123)
- React Query / TanStack Query:设置
staleTime(数据的有效期)和 gcTime(数据在内存中的保留时间)
- 写入时失效 —— 当数据发生变化时,立即删除或更新缓存条目
- 使用缓存旁路模式:先检查缓存,未命中时从源获取,再写入缓存
- 对于 Next.js:利用 ISR(
revalidate)、unstable_cache 和获取缓存的服务器组件
- 基于标签的无效化:按实体类型标记缓存条目,在变更时使该标签的所有条目失效
模式
async function getCachedUser(id: string) {
const cached = await redis.get(`user:${id}`);
if (cached) return JSON.parse(cached);
const user = await db.user.findUnique({ where: { id } });
await redis.set(`user:${id}`, JSON.stringify(user), "EX", 3600);
return user;
}
避免事项
- 不设置 TTL 的缓存 —— 过期数据将无限期存在
- 在共享 CDN 缓存中缓存用户特定数据 —— 应使用
private 或 Vary 头
- 缓存雪崩:使用锁或
stale-while-revalidate 防止惊群效应
- 缓存错误响应 —— 只缓存成功的结果