← 中文资源

简体中文版本

缓存失效

缓存失效决定缓存数据何时不再可信,可通过 TTL、版本化键或显式清除避免读到过期数据。

阅读英文原文

策略

TTL 过期通过无需协调的方式限制陈旧时间:简单,但正确性取决于 TTL 是否可接受。版本化键把版本或内容哈希编码进键,新版本自然未命中,旧条目变得不可达。显式清除在变更后删除键,但需要顺序和重试逻辑。写穿在写入路径同时更新缓存,以写延迟换取更快的读。

const cache = new Map();

async function getUser(id, version) {
  const key = `user:${id}:v${version}`;
  if (cache.has(key)) return cache.get(key);
  const user = await db.users.findById(id);
  cache.set(key, user);
  return user;
}

// 变更时递增版本,旧键不再被使用。
async function renameUser(id, name, currentVersion) {
  await db.users.update(id, { name });
  return currentVersion + 1;
}

写/删竞态

常见序列是:写者更新数据库、删除缓存键;某个读者在更新前读到旧值,却在删除后把旧值写回。版本化键可以避免,因为读者写入旧版本,新读者不再使用它。如果使用显式删除,应在提交后删除,考虑延迟二次删除或使用锁。

何时使用哪种

对于可接受有界陈旧的数据(如公开内容)使用 TTL。对于权限、账户状态和库存,使用版本化键或显式失效。与无缓存相比,失效增加正确性工作;与每次请求读数据库相比,它用新鲜度换取延迟和负载。

陷阱

失效事件可能丢失;应配合重试并以 TTL 兜底。跨服务共享的缓存需要每个键有明确所有者。监控命中率、陈旧读错误和清除失败;一个很快但错误的缓存比没有缓存更糟。

相关资源