缓存相关问题是高并发系统中常见的性能挑战,缓存击穿、缓存穿透、缓存雪崩分别指不同的异常访问场景。下面分别说明其含义、成因与解决方案:
✅ 一、缓存击穿(Cache Breakdown)
❓定义
指某个热点 key 在某一瞬间失效,而此时有大量并发请求访问这个 key,由于缓存失效,请求会同时打到数据库,可能造成数据库压力骤增,甚至崩溃。
📌典型场景
例如商品详情页中一个高频商品的缓存到期,此时大量用户访问,就会同时请求数据库查询该商品信息。
✅解决方案
-
互斥锁(加锁控制)
-
在缓存未命中时,只允许一个线程去查询数据库并写入缓存,其他线程等待或稍后重试。
-
Redis 分布式锁、
ReentrantLock
+ 双重检查(Double Check)是常见做法。
-
-
热点数据永不过期(或延迟异步刷新)
-
对于热点数据设置超长 TTL,同时后台定时异步刷新缓存内容。
-
-
异步更新(如通过消息队列)
-
读取请求不直接更新缓存,而是将 miss 的 key 投递到 MQ,由后台异步更新缓存。
-
✅ 二、缓存穿透(Cache Penetration)
❓定义
指请求的数据在缓存和数据库中都不存在,用户请求会每次都打到数据库,形成大量无效访问。
📌典型场景
攻击者大量请求数据库中不存在的用户ID、商品ID等,绕过缓存防线,击穿数据库。
✅解决方案
-
缓存空对象
-
对于数据库不存在的数据,也缓存一个空值(如 NULL 或特殊标记),并设置较短 TTL。
-
-
布隆过滤器(Bloom Filter)
-
在缓存前使用布隆过滤器拦截不存在的数据请求,节省缓存和数据库资源。
-
适合已知 key 空间有限、较为静态的场景(如商品ID、用户ID等)。
-
-
接口限流+身份校验
-
对恶意请求进行黑名单、IP 限流、验证码校验等手段防护。
-
✅ 三、缓存雪崩(Cache Avalanche)
❓定义
指大量缓存集中在某一时间失效,导致请求全部落到数据库,产生“雪崩”效应。
📌典型场景
缓存预热脚本同时设置了很多缓存 TTL 为 10 分钟,当这批缓存同时到期时,会对数据库造成集中冲击。
✅解决方案
-
随机过期时间
-
为缓存的 TTL 加上一定的随机值,避免集中失效。
long ttl = 3600 + ThreadLocalRandom.current().nextInt(300); // 3600~3900秒
-
-
预热与分批加载
-
缓存预热时分批加载,避免所有 key 同时过期。
-
-
热点数据永不过期 + 后台定期刷新
-
参考击穿中的“异步更新”策略。
-
-
多级缓存架构
-
结合本地缓存(如 Caffeine)+ Redis,分层抗压。
-
🔚 总结对比
问题类型 | 定义 | 影响 | 典型原因 | 常见解决 |
---|---|---|---|---|
缓存击穿 | 热点 key 失效被高并发请求打穿 | 数据库被冲垮 | 缓存 TTL 到期 | 加锁互斥、永不过期、异步更新 |
缓存穿透 | 查询数据不存在,缓存和数据库都无 | 数据库压力 | 恶意请求/异常 ID | 空对象缓存、布隆过滤器、限流 |
缓存雪崩 | 大量缓存同时失效 | 数据库雪崩 | TTL 设置相同 | TTL 随机化、分批过期、后台刷新 |
需要我帮你写一段 Spring Boot 或 Redis 相关的实际代码示例来解决某一类缓存问题吗?