缓存雪崩、击穿、穿透:一次讲清三者的区别与解法

举报
yd_271358468 发表于 2026/11/10 01:16:23 2026/11/10
【摘要】 缓存出问题的时候,表现常常一模一样:数据库突然被打满,接口大面积超时。但背后的原因可能完全不同。雪崩、击穿、穿透这三个词经常被混着用,实际上它们是三种不同的故障模式,解法也不一样。本文把三者分开讲清楚。缓存雪崩:大量缓存同一时间失效雪崩是指同一时间段内,大量缓存同时过期失效,请求全部落到数据库上,数据库瞬间被压垮。常见的原因是缓存设置了相同的过期时间,比如批量预热时统一设了 30 分钟,到点...

缓存出问题的时候,表现常常一模一样:数据库突然被打满,接口大面积超时。但背后的原因可能完全不同。雪崩、击穿、穿透这三个词经常被混着用,实际上它们是三种不同的故障模式,解法也不一样。本文把三者分开讲清楚。

缓存雪崩:大量缓存同一时间失效

雪崩是指同一时间段内,大量缓存同时过期失效,请求全部落到数据库上,数据库瞬间被压垮。常见的原因是缓存设置了相同的过期时间,比如批量预热时统一设了 30 分钟,到点一起失效;或者缓存服务本身宕机,所有请求直接穿透到数据库。

应对雪崩的核心思路是把失效时间打散。给缓存的过期时间加一个随机值,比如基础时间加 0 到 5 分钟的随机偏移,避免同一批缓存在同一秒过期。热点数据可以设置永不过期,由后台任务异步刷新,而不是等它过期再由请求触发加载。

另一个办法是多级缓存。本地缓存挡住第一波,分布式缓存挡第二波,数据库只承担最后的少量请求。即使分布式缓存整体失效,本地缓存还能撑一阵,给系统留出恢复时间。降级熔断也是最后一道防线:当数据库负载过高时,直接返回默认值或旧数据,先保住系统不崩。

缓存击穿:单个热点 key 过期

击穿和雪崩的区别在于规模:击穿是某一个热点 key 过期了,同一瞬间大量请求都在访问这个 key,全部打到数据库上。比如一个爆款商品的详情页缓存过期,几万个并发请求同时去查数据库,数据库扛不住。

击穿的解法是互斥锁。第一个请求发现缓存 miss 后去拿锁,拿到锁的去查数据库并回填缓存,其他请求等一小会儿再去读缓存。锁的粒度要控制在单个 key 上,不能一把全局锁锁住所有请求,否则并发一上来就全堵住了。

更稳妥的做法是热点 key 永不过期加异步刷新。后台定时任务在缓存快过期前主动刷新,请求永远读得到缓存,根本不会出现 miss。逻辑过期是另一种实现:缓存里存一份过期时间字段,数据本身不过期,读到逻辑过期的数据时由一个线程去刷新,其他线程继续返回旧数据,避免所有请求同时回源。

缓存穿透:请求查的是不存在的数据

穿透是指请求查询的数据根本不存在,缓存里没有,数据库里也没有,于是每次请求都穿过缓存打到数据库。攻击者可以故意用不存在的 ID 轮询,数据库被大量无效查询拖垮。正常业务里也有这种情况,比如用户输入了错误的订单号、爬虫遍历不存在的商品 ID。

最简单的防线是空值缓存。数据库查不到时,也往缓存里写一个空值并设置较短的过期时间,下次同样的请求直接命中空值,不再查库。要注意空值缓存的过期时间不能太长,否则数据刚写入时,请求还会拿到旧的空值。

布隆过滤器是更彻底的办法。在请求到达缓存之前,先用布隆过滤器判断这个 key 是否可能存在,不存在就直接返回,不查缓存也不查数据库。布隆过滤器有一定的误判率,但它只会把不存在的误判为存在,不会把存在的误判为不存在,所以是安全的。维护成本在于要把所有合法 key 同步进过滤器,新增数据时要及时更新。

参数校验也别忽视。很多穿透请求其实一眼就能看出来不合法:ID 格式不对、范围明显越界,这类请求在网关层直接拦截,根本不用进到缓存和数据库。

三者怎么区分,怎么选解法

从现象上区分:雪崩是大量不同 key 同时失效,数据库压力来自全量请求;击穿是单个热点 key 失效,压力集中在一条查询上;穿透是请求的数据本身不存在,缓存永远命中不了。

解法上也可以对照着记:雪崩靠打散过期时间和多级缓存,击穿靠互斥锁和逻辑过期,穿透靠空值缓存和布隆过滤器。实际项目里三种问题可能同时出现,防护手段也要叠加使用。

最后一点经验:缓存问题大多不是缓存本身的问题,而是过期策略和回源策略没设计好。上线前把热点 key 的过期时间、空值处理、并发回源这三件事想清楚,能避免绝大多数线上事故。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。