redis缓存雪崩,击穿,穿透,到底是什么?

Redis 缓存雪崩、击穿、穿透 是缓存使用中最经典的三大“灾难级”问题,几乎所有中大型系统都会遇到,也几乎是面试中 Redis 相关问题出现频率 Top 3 的概念。

下面用最通俗、最容易记住的方式给你讲清楚三者的定义、成因、危害、区别、解决方案

一张表先看清三者的本质区别

问题名称什么时候发生核心原因影响范围表现形式典型场景举例
缓存穿透查询一个根本不存在的数据请求直接打到数据库单个 key 反复打穿数据库压力瞬间暴增黑客猜用户 ID、恶意爬虫刷不存在的商品 ID
缓存击穿某个热点 key 突然过期大量并发同时请求同一个已过期 key单个热点 key瞬间把数据库打崩秒杀商品、热门文章、直播间人数
缓存雪崩大量 key 在同一时间点集体失效大量缓存同时过期 + 冷启动几乎所有 key数据库像雪崩一样瞬间被打垮双11零点、促销活动统一设置了相同过期时间

详细解释 + 生活化比喻

1. 缓存穿透(Cache Penetration)

比喻
你去一个从没开过门的店问“有没有黄金项链”,老板每次都要去仓库翻一遍告诉你“没有”,你一天问 10 万次,老板累死了。

成因

  • 查询一个数据库里压根不存在的数据
  • 缓存里自然也没有 → 每次都穿透到数据库

最危险的几种情况

  • 恶意攻击(枚举不存在的 ID)
  • 前端传了非法参数(负数 ID、空字符串、超大值)
  • 数据库里数据被删除了,但缓存没清理

解决方案(按优先级排序):

  1. 缓存空结果(最常用)
   if (redis.get(key) == null) {
       Object obj = db.query(id);
       if (obj == null) {
           redis.setex(key, 60, "EMPTY");  // 缓存空值,短过期时间
       } else {
           redis.setex(key, 3600, obj);
       }
   }
  1. 布隆过滤器(适合黑客攻击场景)
  • 在缓存前加一层布隆过滤器,提前判断 key 肯定不存在就直接返回
  1. 接口参数校验 + 限流 + IP 黑名单

2. 缓存击穿(Cache Breakdown / Hot Key 失效)

比喻
商场里最火的那件限量款羽绒服突然卖完了(缓存过期),门口瞬间挤了几千人同时问“还有货吗”,全都冲到仓库去问老板。

成因

  • 一个极热的 key(QPS 几千上万)
  • 恰好在这个时间点过期
  • 大量请求同时穿透到数据库

解决方案(目前主流做法):

  1. 永不过期 + 逻辑过期(最推荐)
   // 缓存里存两个字段:data + expireTime
   if (now > expireTime) {
       // 异步线程去刷新
       asyncRefresh(key);
       return oldData;  // 先返回旧数据
   }
  1. 加分布式锁(setnx / Redisson lock)
  • 只有一个请求去查数据库,其他请求等待或返回旧数据
   if (lock.tryLock(10, TimeUnit.SECONDS)) {
       try {
           // 双重检查
           if (redis.get(key) == null) {
               redis.setex(key, 3600, db.query());
           }
       } finally {
           lock.unlock();
       }
   }
  1. 热点 key 预加载 / 随机偏移过期时间

3. 缓存雪崩(Cache Avalanche)

比喻
商场里 80% 的商品同时到保质期,全都下架了,几万人同时冲向仓库,仓库直接被挤爆。

成因

  • 大量 key 在同一时间点过期
  • 或者缓存服务器宕机 / 重启 / 冷启动

解决方案(多管齐下):

  1. 过期时间加随机值
   redis.setex(key, 3600 + random(300, 600), value);  // 1小时 ± 几分钟
  1. 多级缓存(本地缓存 + Redis)
  • Caffeine / Guava Cache 做一级,本地命中就不打 Redis
  1. 热点数据永不过期 + 定时任务后台刷新
  2. Redis 集群 + 主从 + 哨兵,避免单点宕机
  3. 熔断 / 降级 / 限流(Hystrix、Resilience4j、Sentinel)
  4. 缓存预热(启动时把热点数据提前加载)

三者对比总结口诀(面试背这个就够)

  • 穿透:查根本不存在的东西 → 缓存空对象 / 布隆过滤器
  • 击穿一个超级热点突然没了 → 分布式锁 / 逻辑过期 / 永不过期
  • 雪崩一大堆 key同时没了 → 随机过期 + 多级缓存 + 预热

一句话记住
穿透是“查鬼”,击穿是“抢购疯抢一件”,雪崩是“商场同时清仓”。

你现在项目里有没有遇到过这三个问题中的哪一个?
或者想看某个具体解决方案的代码示例(比如分布式锁防击穿、布隆过滤器防穿透)?可以继续问~

文章已创建 4237

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部