云计算百科
云计算领域专业知识百科平台

缓存穿透、雪崩、击穿:三大故障全解析

缓存穿透 缓存雪崩 缓存击穿这三者是缓存架构中最常见的三类故障场景,核心差异在于触发原因、影响范围和应对策略,从底层原理到解决方案可以这样拆解:

一、 缓存穿透

1. 定义

指请求的数据在缓存和数据库中都不存在,每次请求都会穿透缓存直接打到数据库,导致数据库压力骤增,甚至被打垮。

  • 典型场景:恶意攻击(如构造大量不存在的 key 发起请求)、业务逻辑疏漏(如查询参数错误)。
  • 底层影响:缓存命中率极低,数据库频繁执行无意义的查询,连接池被占满,正常请求无法响应。
    2. 核心应对策略
    策略原理优缺点
    空值缓存 数据库查询为空时,将 key 对应的空值(如 null)写入缓存,并设置短过期时间(如 5 分钟) 优点:实现简单;缺点:会占用少量缓存空间,可能被恶意 key 撑爆
    布隆过滤器 启动时将数据库中所有有效 key 预加载到布隆过滤器中,请求先经过过滤器校验,不存在的 key 直接拦截 优点:空间效率极高,拦截效率接近 100%;缺点:存在误判率(无法区分 “一定不存在” 和 “可能存在”),不支持删除操作
    请求限流 / 校验 对接口做参数合法性校验,对异常请求频率的 IP 进行限流 优点:从源头拦截恶意请求;缺点:无法应对正常业务的无效查询

3. 代码示例(空值缓存)

public Object getValue(String key) {
// 1. 先查缓存
Object cacheValue = redisTemplate.opsForValue().get(key);
if (cacheValue != null) {
return cacheValue;
}
// 2. 缓存未命中,查数据库
Object dbValue = dbMapper.selectByKey(key);
if (dbValue == null) {
// 3. 数据库无数据,缓存空值并设置短过期时间
redisTemplate.opsForValue().set(key, null, 5, TimeUnit.MINUTES);
return null;
}
// 4. 数据库有数据,缓存并返回
redisTemplate.opsForValue().set(key, dbValue, 30, TimeUnit.MINUTES);
return dbValue;
}

二、 缓存雪崩

1. 定义

指大量缓存数据在同一时间点过期,导致所有请求瞬间穿透到数据库,数据库因压力过载而宕机,进而引发整个系统雪崩。

  • 典型场景:缓存集群重启、批量设置相同的过期时间(如促销活动结束时间统一)。
  • 底层影响:短时间内数据库请求量飙升,CPU/IO 打满,服务雪崩效应(一层故障蔓延到多层)。
2. 核心应对策略
策略原理优缺点
过期时间随机化 给每个 key 的过期时间增加随机偏移量(如基础过期时间 30 分钟 ± 5 分钟),避免集中过期 优点:实现简单,无额外成本;缺点:无法解决缓存集群宕机的场景
多级缓存架构 引入本地缓存(如 Caffeine) + 分布式缓存(如 Redis),分布式缓存失效时,本地缓存可兜底 优点:降低分布式缓存依赖;缺点:本地缓存存在一致性问题,占用 JVM 堆内存
缓存预热 + 降级限流 系统启动前提前加载热点数据到缓存;缓存失效时,对数据库请求进行限流降级,返回兜底数据 优点:应对突发流量;缺点:实现复杂,需要配套监控和熔断机制
集群高可用 使用 Redis 哨兵 / 集群模式,避免单节点宕机导致的缓存全量失效 优点:解决硬件故障;缺点:无法解决业务层的集中过期问题

3. 代码示例(过期时间随机化)

public void setValue(String key, Object value) {
// 基础过期时间 30 分钟,随机偏移 0-5 分钟
int baseExpire = 30 * 60;
int randomExpire = new Random().nextInt(5 * 60);
int totalExpire = baseExpire + randomExpire;
redisTemplate.opsForValue().set(key, value, totalExpire, TimeUnit.SECONDS);
}

三、 缓存击穿

1. 定义

指某个热点 key 突然过期,此时恰好有大量并发请求访问该 key,所有请求都会穿透到数据库,导致数据库瞬间压力暴增。

  • 核心区别于雪崩:击穿是单个热点 key 的问题,雪崩是大量 key 的问题。
  • 典型场景:秒杀商品的缓存过期、热门资讯的缓存失效。
2. 核心应对策略
策略原理优缺点
互斥锁 缓存未命中时,通过分布式锁(如 Redis Redlock)保证只有一个请求去数据库查询并更新缓存,其他请求等待 优点:逻辑严谨,一致性强;缺点:存在锁竞争,高并发下有性能损耗
热点数据永不过期 对热点 key 不设置过期时间,由后台异步任务定期更新缓存 优点:无过期穿透风险;缺点:需要维护热点 key 列表,缓存空间占用较高
缓存预热 + 延长过期时间 提前将热点数据加载到缓存,并设置较长的过期时间,结合监控实时刷新 优点:简单高效;缺点:依赖热点数据的预判能力

3. 代码示例(互斥锁方案)

public Object getHotValue(String key) {
// 1. 查缓存
Object cacheValue = redisTemplate.opsForValue().get(key);
if (cacheValue != null) {
return cacheValue;
}
// 2. 缓存未命中,加分布式锁
String lockKey = "lock:" + key;
Boolean lock = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 3, TimeUnit.SECONDS);
if (lock != null && lock) {
try {
// 3. 拿到锁,查数据库并更新缓存
Object dbValue = dbMapper.selectByKey(key);
redisTemplate.opsForValue().set(key, dbValue, 30, TimeUnit.MINUTES);
return dbValue;
} finally {
// 4. 释放锁
redisTemplate.delete(lockKey);
}
} else {
// 5. 未拿到锁,自旋等待(或返回兜底数据)
Thread.sleep(50);
return getHotValue(key);
}
}

四、 三者核心区别总结

维度缓存穿透缓存雪崩缓存击穿
数据存在性 缓存 + 数据库都不存在 缓存存在,批量过期 缓存过期,数据库存在
影响范围 所有无效 key 的请求 所有请求 单个热点 key 的请求
触发原因 恶意攻击 / 业务疏漏 集中过期 / 集群宕机 热点 key 过期 + 高并发
核心关键词 空值、布隆过滤器 随机过期、多级缓存 分布式锁、热点永不过期
赞(0)
未经允许不得转载:网硕互联帮助中心 » 缓存穿透、雪崩、击穿:三大故障全解析
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!