标准答案

  1. 读取时先判断 expiresAt,过期就删除并返回未命中。
  2. 超过最大容量时按 LRU、LFU 或近似策略淘汰,不能把过期数据当作有效容量。
  3. 定期扫描或维护过期队列做主动清理,并让并发读写有明确同步边界。

题目解析

TTL 表达某条数据何时不再有效,最大容量淘汰表达内存不足时先删除谁,两者不能互相替代。一个 Key 即使 TTL 很长,也可能在内存压力下先被淘汰。

惰性清理只在访问时发现过期 Key,冷 Key 可能长期占用空间,因此要配合定期扫描、过期队列或存储自身的主动过期。扫描也要有批量和时间上限,避免清理任务阻塞主路径。

并发读写要明确 Map、淘汰链表和过期状态的同步边界。淘汰策略还应结合热点、对象大小和业务重建成本,不能只追求命中率。

代码示例

缓存项的核心判断:

TypeScript
const item = map.get(key)
if (!item || item.expiresAt <= clock.now()) {
  map.delete(key)
  return undefined
}
return item.value

常见误区

  • 误区:为每个 Key 创建独立 setTimeout。改正:大规模缓存使用惰性加批量主动清理,避免定时器数量失控。
  • 误区:过期读取不删除。改正:返回未命中的同时删除或标记过期,容量统计不能把无效项算作有效缓存。
  • 误区:淘汰策略没有说明并发和热点影响。改正:说明锁、近似 LRU/LFU、对象大小和热点重建成本。

作者信息