缓存穿透、击穿、雪崩

缓存穿透:查"不存在的东西"

  • 缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如用非法ID、无效参数查询等,导致缓存无法命中,所有请求直接穿透到数据库。

核心原因

  1. 恶意攻击:黑客用大量无效 ID 发起请求,意图压垮数据库。
  2. 业务误操作:代码逻辑错误,查询了不存在的资源。

解决方案

  • 空值缓存:数据库查询返回空时,仍将"空结果"存入缓存(设置较短过期时间,如 1-5 分钟),避免重复穿透。
  • 布隆过滤器:在缓存前加一层布隆过滤器,提前拦截 "肯定不存在的数据",无需查询缓存和数据库。
  • 参数校验:接口层先校验参数合法性(如 ID 格式、范围),直接拒绝无效请求。

缓存击穿:热点key"突然失效"

  • 某个高频访问的热点key(如秒杀商品、热门活动页面)突然过期或缓存宕机,瞬间大量请求打向数据库,导致数据库压力骤增。换句话说:缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。

核心原因

  1. 热点 key 过期:缓存设置了统一过期时间,到期后同时失效。
  2. 缓存宕机:存储热点 key 的缓存节点故障,无法提供服务。

解决方案

  • 互斥锁:缓存未命中时,只有一个线程能查询数据库,其他线程等待结果并复用缓存,避免"并发穿透"。
  • 热点key永不过期:核心热点key不设置过期时间,通过后台异步更新缓存内容。
  • 熔断降级:当数据库压力超过阈值时,返回默认数据(如"系统繁忙,请稍后重试"),保护数据库。

缓存雪崩:大量key"集体失效"

  • 大规模缓存key集中过期,或缓存集群整体宕机,导致海量请求同时穿透到数据库,直接压垮数据库。(和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。)

核心原因

  1. 过期时间集中:初始化时给大量key设置了相同过期时间(如凌晨1点),到期后集体失效。
  2. 缓存集群故障:缓存集群(如Redis集群)因网络、硬件问题整体不可用。

解决方案

  • 过期时间 "打散":给每个 key 的过期时间加随机值(如基础过期 1 小时 + 0-30 分钟随机值),避免集中失效。
  • 缓存集群高可用:部署主从复制、哨兵模式或集群模式,确保单个节点故障时,其他节点能接替服务。
  • 限流降级:前端限流 + 后端降级,限制同时访问数据库的请求数,超出部分返回默认值。
  • 数据库兜底:给数据库配置读写分离、连接池扩容,提升抗压能力。

三者核心区别

问题 触发场景 影响范围 核心矛盾
穿透 查询不存在的数据 分散请求,持续存在 无效请求穿透到数据库
击穿 单个热点 key 失效 集中请求,瞬间爆发 热点请求无缓存承接
雪崩 大量 key / 集群失效 海量请求,全面爆发 缓存整体失去防护能力