什么是缓存穿透,如何解决?

考查重点:不存在键访问与数据库保护。不存在的数据反复穿过缓存查数据库;参数校验、短期空值和布隆过滤分层拦截,注意新数据加入与误判处理

本题目录

参考答案

核心回答

缓存穿透是指请求查询的数据在缓存和数据库中都不存在,未命中结果又没有被有效拦截或缓存,导致相同或大量不存在的键反复查询数据库。它可能来自恶意构造的 ID,也可能来自旧链接、删除后的数据等正常请求。

通常分层治理:

  1. 入口校验与限流。 拒绝明显无效的参数,限制异常请求及数据库回源量。
  2. 缓存“不存在”的结果。 数据库明确查无数据后,写入可识别的空值标记并设置较短 TTL,后续相同请求直接返回;标记要与“缓存未命中”区分。
  3. 用布隆过滤器过滤大量随机键。 将可查询的 ID 加入过滤器,判断确定未收录的键可提前拦截;判断可能存在的键仍正常查缓存和数据库。前提是过滤器已完整构建,并能及时同步新数据。

空值缓存适合重复访问同一个不存在的键;布隆过滤器更适合拦截大量不同的不存在键。两者可结合,但仍需控制回源,避免误判、同步延迟或组件故障把压力全部转给数据库。

空值缓存要处理哪些细节

以商品详情为例:先查商品缓存,命中商品值就返回,命中“不存在”标记就返回未找到;真正未命中时再查数据库,查到商品则写正常缓存,明确没有记录才写短期空值。

TTL 要结合新数据可见性的要求选择。过长会让后来创建的商品继续被当成不存在;过短则增加回源。创建商品提交成功后,应清理相应空值,失败时有重试,TTL 作为兜底。并发中的旧查询仍可能晚于清理写回空值;若业务不接受这段窗口,需要进一步协调回填与创建,不能只依赖一次删除。

数据库超时、连接失败不代表“商品不存在”,不能统一缓存成未找到。可以按业务返回暂时不可用,或单独短期缓存错误状态以抑制重试,但应保留它与业务空结果的区别。

随机键攻击还可能灌入大量空值,占满缓存,因此需要限制空值缓存规模、保留时间和入口流量,而不是无限缓存所有无效 ID。

布隆过滤器为什么会误判

布隆过滤器使用多个哈希函数把 ID 映射到位数组。查询时只要有一位为 0,就能判断该 ID 没被加入;如果对应位都是 1,可能是这个 ID,也可能由其他 ID 的映射共同造成,所以会出现假阳性。

这个性质针对的是已加入过滤器的集合。数据库新增记录尚未同步、过滤器丢失或重建未完成时,数据库中的真实商品也可能未被收录。此时不能把过滤器的负结果直接当成业务不存在,应识别过滤器的就绪状态,并按可用性要求采用受限回源等策略。布隆过滤器本身不提供数据库与过滤器的原子更新。

误判率越低通常需要越多空间或计算;容量增长也要规划。普通布隆过滤器的位可能由多个元素共享,删除商品时不能随便清零对应位,否则可能影响其他 ID;保留这些位会多放行一些查询,可以通过受控重建等方式治理。

追问:加锁或者随机 TTL 能解决穿透吗

同键请求合并或互斥回源可以减少并发查库,但如果每次查不到都不保存结果,下次仍会回源;对大量不同键,逐键加锁也难以解决总体压力。

随机 TTL 主要缓解大量缓存集中失效。热点数据存在、缓存失效后被大量请求同时重建,通常称为缓存击穿;大量不存在的数据反复回源才是这里的穿透。要根据数据库是否有数据、请求是否集中在同一键,以及回源量来判断,不能只凭“缓存命中率下降”下结论。

参考资料

相关面经

5 篇

水滴

AI全栈
校招一面
查看原面经 →
如何解决缓存穿透?

百度

面经合集
查看原面经 →
什么是缓存穿透?
追问
除布隆过滤器外,还有什么解决办法?

字节跳动

AI 应用开发工程师
日常实习一面
查看原面经 →
什么是缓存穿透?
追问
缓存穿透一般怎么解决?

快手

后端开发
日常实习一面
查看原面经 →
c. 你项目里用了 Redis,怎么防止缓存穿透?

腾讯

后端开发工程师
一面
查看原面经 →
什么是缓存穿透,如何解决缓存穿透

相关题目

4 题