返回首页
Redis

缓存穿透、击穿与雪崩:三个相似名词的因果区别

缓存穿透、击穿和雪崩都会把压力传递到数据库,但三者的原因不同。区分它们最简单的方法,是观察请求的 key 是否存在、影响的是单个热点还是大量 key。

缓存穿透:查询不存在的数据

攻击者或异常调用持续请求不存在的 key,缓存中没有,数据库里也没有,所以每次请求都会穿过缓存。

常见手段:

  • 参数校验和接口限流;
  • 对空结果设置较短 TTL;
  • 使用布隆过滤器快速排除一定不存在的数据。

布隆过滤器可能误判“存在”,但不会把真实存在的数据判断为不存在。它节省了大量无效查询,却需要解决数据新增时同步更新的问题。

缓存击穿:单个热点突然失效

一个访问量很高的 key 到期,大量并发请求同时回源数据库,形成瞬时冲击。

可以使用互斥锁或 single-flight,只让一个请求负责加载数据,其余请求等待结果;也可以采用逻辑过期,让旧值短暂可用,由后台线程刷新。

这里存在可用性与一致性的权衡:等待加载保证结果较新,但增加延迟;返回旧值响应更稳,却允许短暂过期数据。

缓存雪崩:大量 key 同时失效

大量缓存使用相同 TTL,或 Redis 整体故障,会让大范围请求同时回到数据库。这不是一把热点锁就能解决的问题。

常见治理包括:

  • TTL 加入随机抖动,避免同时过期;
  • 热点数据预热和分批刷新;
  • Redis 高可用与容量监控;
  • 服务侧限流、熔断、降级;
  • 数据库连接池和查询资源设置明确上限。

缓存不是越多越好

引入缓存后,系统从单一数据源变成多份副本,需要处理更新顺序、失效、重试和监控。设计方案时我会先明确可接受的不一致时间,再选择 Cache Aside 等策略,并为 Redis 不可用准备降级路径。