Skip to content
作者:daily5am创建:-更新:-
字数:预计阅读: 分钟访问量:--

Redis缓存穿透、击穿、雪崩

AI生成声明: 本文档由AI辅助生成,旨在提供Redis缓存穿透、击穿、雪崩问题的完整解决方案。

缓存穿透、击穿、雪崩是Redis使用中的三大经典问题,理解并解决这些问题对于保证系统稳定性至关重要。

核心问题

缓存穿透(Cache Penetration)

定义:

  • 查询不存在的数据
  • 缓存和数据库都没有
  • 大量请求直接打到数据库

原因:

  • 恶意攻击
  • 业务逻辑缺陷
  • 数据确实不存在

解决方案:

  1. 布隆过滤器

    java
    // 查询前先检查布隆过滤器
    if (!bloomFilter.mightContain(key)) {
        return null;
    }
  2. 缓存空值

    java
    // 即使数据不存在也缓存
    if (data == null) {
        redis.set(key, "", 60); // 设置短过期时间
    }
  3. 参数校验

    • 对请求参数进行校验
    • 过滤非法请求

缓存击穿(Cache Breakdown)

定义:

  • 热点数据过期
  • 大量请求同时访问数据库
  • 数据库压力骤增

原因:

  • 热点数据过期
  • 并发访问量大

解决方案:

  1. 互斥锁

    java
    // 使用分布式锁
    String lockKey = "lock:" + key;
    if (redis.setNx(lockKey, "1", 10)) {
        try {
            data = loadFromDB();
            redis.set(key, data);
        } finally {
            redis.del(lockKey);
        }
    } else {
        // 等待其他线程加载
        Thread.sleep(100);
        return getFromCache(key);
    }
  2. 永不过期

    • 热点数据设置永不过期
    • 异步更新缓存
  3. 提前续期

    • 在过期前异步刷新
    • 保证数据始终可用

缓存雪崩(Cache Avalanche)

定义:

  • 大量缓存同时过期
  • 大量请求打到数据库
  • 数据库压力过大

原因:

  • 缓存过期时间设置相同
  • Redis服务宕机
  • 大量数据同时失效

解决方案:

  1. 过期时间随机化

    java
    // 在基础时间上增加随机值
    int expireTime = 3600 + random.nextInt(600);
    redis.set(key, value, expireTime);
  2. 多级缓存

    • 本地缓存 + Redis
    • 降低Redis压力
  3. 熔断降级

    • 检测到异常时熔断
    • 返回默认值或错误提示
  4. 高可用架构

    • Redis主从 + 哨兵
    • Redis Cluster集群

预防措施

  1. 监控告警

    • 监控缓存命中率
    • 监控数据库QPS
    • 设置告警阈值
  2. 限流

    • 对数据库访问限流
    • 保护数据库
  3. 降级策略

    • 缓存不可用时降级
    • 返回默认数据

常见面试题

  1. 三种问题的区别?

    • 穿透:数据不存在
    • 击穿:热点数据过期
    • 雪崩:大量数据同时过期
  2. 如何预防缓存雪崩?

    • 过期时间随机化
    • 多级缓存
    • 高可用架构
  3. 布隆过滤器的原理?

    • 位数组 + 多个哈希函数
    • 可能存在误判
    • 不存在一定不存在