乐趣区

关于缓存:缓存穿透缓存雪崩缓存击穿的区别以及解决方法

缓存穿透

缓存和数据库均不存在(申请打到缓存,未查问到,接着查询数据库,也没有查到)时,大量并发会对数据库造成极大压力。

解决方案

  1. 设置一个 key-null 的缓存,并将生效工夫能够设置短一点(比方 30s), 这样雷同申请就不会间接打到数据库。
  2. 应用 BloomFilter,相当于在查问缓存之前先在汇合中查问 key 是否存在,如果不存在就间接返回
    • *

缓存雪崩

同一时刻大量缓存生效,导致申请全部打到数据库。

解决方案

  1. 缓存数据的过期工夫设置随机,避免同一时间大量数据过期景象产生
  2. 如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中
  3. 设置热点数据永不过期
    • *

缓存击穿

缓存雪崩的一种,雪崩是多个 key 生效,击穿是指某个 key 生效,同一时刻,大量的雷同申请会间接打到数据库。

解决方案

  1. 设置热点数据永不过期。
  2. 采纳互斥锁
static Lock reenLock = new ReentrantLock();

public List<String> getData() throws InterruptedException {List<String> result = new ArrayList<String>();
    // 从缓存读取数据
    result = getDataFromCache();
    if (result.isEmpty()) {if (reenLock.tryLock()) {
            try {System.out.println("我拿到锁了, 从 DB 获取数据库后写入缓存");
                // 从数据库查问数据
                result = getDataFromDB();
                // 将查问到的数据写入缓存
                setDataToCache(result);
            } finally {reenLock.unlock();// 开释锁
            }

        } else {result = getDataFromCache();// 先查一下缓存
            if (result.isEmpty()) {System.out.println("我没拿到锁, 缓存也没数据, 先小憩一下");
                Thread.sleep(100);// 小憩一会儿
                return getData();// 重试}
        }
    }
    return result;
}
退出移动版