侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1824 篇文章
  • 累计收到 0 条评论

分布式缓存中缓存击穿与缓存雪崩的区别及解决方案

2025-12-12 / 0 评论 / 2 阅读

题目

分布式缓存中缓存击穿与缓存雪崩的区别及解决方案

信息

  • 类型:问答
  • 难度:⭐

考点

缓存击穿概念,缓存雪崩概念,分布式缓存解决方案

快速回答

缓存击穿和缓存雪崩是分布式缓存的常见问题:

  • 缓存击穿:热点数据失效瞬间,大量请求直接压垮数据库
  • 缓存雪崩:大量缓存同时过期,导致数据库请求激增
  • 解决方案
    • 击穿:互斥锁、永不过期策略
    • 雪崩:随机过期时间、缓存高可用
## 解析

1. 原理说明

缓存击穿:当某个热点Key突然过期时,海量请求直接穿透缓存访问数据库,导致数据库瞬时压力过大。

缓存雪崩:大量缓存数据在相近时间点集中过期,引发连锁反应式的数据库访问洪峰。

2. 解决方案对比

问题类型解决方案实现方式
缓存击穿互斥锁 (Mutex Lock)只允许一个线程重建缓存
永不过期策略逻辑过期时间+后台更新
缓存雪崩随机过期时间基础过期时间+随机偏移值
缓存高可用Redis Cluster/Memcached多节点

3. 代码示例(Java+Redis)

// 解决缓存击穿 - 互斥锁实现
public String getData(String key) {
    String value = redis.get(key);
    if (value == null) { // 缓存失效
        String lockKey = "lock:" + key;
        if (redis.setnx(lockKey, "1", 10)) { // 获取分布式锁
            try {
                value = db.query(key);  // 查数据库
                redis.setex(key, 60, value); // 写缓存
            } finally {
                redis.del(lockKey); // 释放锁
            }
        } else {
            Thread.sleep(50); // 等待重试
            return getData(key);
        }
    }
    return value;
}

// 解决缓存雪崩 - 设置随机过期时间
redis.setex(key, 60 + new Random().nextInt(30), value); // 60-90秒随机过期

4. 最佳实践

  • 击穿防护:热点数据永不过期+异步更新
  • 雪崩防护
    • 过期时间 = 基础时间 + 随机偏移(如30%)
    • Redis Cluster部署保证高可用
  • 监控报警:实时监控缓存命中率

5. 常见错误

  • ❌ 对所有Key使用固定过期时间
  • ❌ 忽略热点Key的特殊处理
  • ❌ 未设置锁超时导致死锁(示例代码中setnx的10秒超时很关键)

6. 扩展知识

  • 缓存穿透:查询不存在的数据(解决方案:布隆过滤器)
  • 数据一致性:延迟双删策略(先删缓存→更新DB→延时再删缓存)
  • 工具推荐:Redisson分布式锁、Spring Cache注解