Redis 缓存穿透、击穿、雪崩:三种故障的边界与兜底

举报
yd_216394844 发表于 2026/10/25 14:33:42 2026/10/25
【摘要】 这三个词经常被混着用,但它们解决的是不同问题。区分清楚才不会上错方案。一、穿透:查一个数据库里根本不存在的 key。缓存必然不命中,请求全部打到数据库。如果有人拿随机 ID 刷接口,数据库会被打穿。两个解法:一是缓存空值,查不到也写一个短过期的空标记,缺点是会占内存,被刷时要用布隆过滤器兜一层;二是布隆过滤器前置,把所有存在的 key 哈希进位数组,不存在的直接拦掉。布隆过滤器有误判率,判断...

这三个词经常被混着用,但它们解决的是不同问题。区分清楚才不会上错方案。

一、穿透:查一个数据库里根本不存在的 key。缓存必然不命中,请求全部打到数据库。如果有人拿随机 ID 刷接口,数据库会被打穿。两个解法:一是缓存空值,查不到也写一个短过期的空标记,缺点是会占内存,被刷时要用布隆过滤器兜一层;二是布隆过滤器前置,把所有存在的 key 哈希进位数组,不存在的直接拦掉。布隆过滤器有误判率,判断存在可能不存在,判断不存在一定不存在,所以只能用来挡穿透,不能替代真实查询。

二、击穿:单个热点 key 突然过期,瞬间大量并发同时回源。注意是单个 key,不是大面积。解法是互斥重建:只让一个请求去查数据库并回填,其他请求等待或者返回旧值。用 Redis 的 setnx 加过期时间做分布式锁,注意锁要设超时,否则持有者挂掉就死锁。另一种是逻辑过期,value 里存一个过期时间戳但不设 TTL,读到逻辑过期后异步刷新,返回旧值,可用性优先的场景更合适。

三、雪崩:大量 key 在同一时间点集中失效,或者 Redis 整体挂掉。前者是因为批量预热时 TTL 设成一样,解法是给过期时间加随机偏移,比如基础 30 分钟加 0 到 5 分钟的随机值。后者要靠架构:主从加哨兵或者集群、本地缓存做二级兜底、限流降级保护数据库。数据库前面加一层熔断,Redis 挂了也不至于把库打穿。

排查顺序:先看 Redis 命中率,命中率骤降说明有穿透或者大面积过期;再看数据库 QPS 曲线,尖峰对应击穿或者雪崩;最后看慢查询和连接数,连接数打满通常是穿透。

几个容易写错的地方:空值缓存一定要设过期,不设就等于内存泄漏;互斥锁的 key 要带业务前缀,避免和正常缓存冲突;逻辑过期方案里刷新失败的 key 要能重试,不然会一直返回旧值;预热脚本要做分批,别一次性灌几十万 key 把 Redis 内存打满。

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

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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