Redis缓存穿透、击穿、雪崩:区别、识别与应对方案

举报
yd_283936595 发表于 2026/11/04 10:21:12 2026/11/04
【摘要】 一、三个问题的区别缓存是保护数据库的第一道防线,但使用不当会让压力瞬间压到数据库上。穿透、击穿、雪崩常被混淆,其实触发原因不同。缓存穿透:请求的数据在缓存和数据库中都不存在,例如恶意用 id=-1 反复查询商品。每次都会落到数据库,缓存形同虚设。缓存击穿:某个热点 key 恰好过期,大量并发请求同时发现缓存缺失,一起去查数据库。典型场景是秒杀商品详情页。缓存雪崩:大量 key 在同一时间集...

一、三个问题的区别

缓存是保护数据库的第一道防线,但使用不当会让压力瞬间压到数据库上。穿透、击穿、雪崩常被混淆,其实触发原因不同。

缓存穿透:请求的数据在缓存和数据库中都不存在,例如恶意用 id=-1 反复查询商品。每次都会落到数据库,缓存形同虚设。

缓存击穿:某个热点 key 恰好过期,大量并发请求同时发现缓存缺失,一起去查数据库。典型场景是秒杀商品详情页。

缓存雪崩:大量 key 在同一时间集中过期,或者 Redis 实例宕机,导致海量请求直接冲击数据库。

二、如何识别

  • 数据库 QPS 突然飙升,而 Redis 命中率(keyspace_hits 与 keyspace_misses 之比)明显下降;
  • 穿透:慢日志里出现大量查询结果为空的 SQL,且参数异常;
  • 击穿:压力集中在个别 key,可用 redis-cli --hotkeys 排查热点;
  • 雪崩:监控显示同一时间点过期的 key 数量陡增,或者 Redis 连接全部失败。

三、应对方案

1. 穿透

  • 接口层做参数校验,非法 id 直接拦截;
  • 对查询为空的结果缓存一个空值,TTL 设置为 60 秒左右;
  • 使用布隆过滤器,启动时把所有合法 id 加载进去,不存在的请求直接返回。

2. 击穿

  • 热点数据设置逻辑过期,由后台线程异步刷新;
  • 使用互斥锁,只允许一个线程重建缓存:
def get_item(item_id):
    val = redis.get(f"item:{item_id}")
    if val:
        return val
    if redis.set(f"lock:{item_id}", 1, nx=True, ex=10):
        val = db.query(item_id)
        redis.set(f"item:{item_id}", val, ex=600)
        redis.delete(f"lock:{item_id}")
        return val
    time.sleep(0.05)
    return get_item(item_id)

3. 雪崩

  • 过期时间加随机值,例如 600 秒加上 0 到 120 秒的随机数,避免集中失效;
  • Redis 采用主从加哨兵或者集群部署,保证高可用;
  • 在应用层增加限流、熔断和降级,数据库前面再放一层本地缓存。

四、小结

穿透是查不存在的数据,击穿是单个热点过期,雪崩是大面积失效。线上建议组合使用:参数校验加布隆过滤器、热点互斥锁、随机过期时间,并持续监控命中率,才能让缓存真正稳定。

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

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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