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

缓存穿透

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

解决方案

  1. 设置一个key-null的缓存,并将失效时间可以设置短一点(比如30s), 这样相同请求就不会直接打到数据库。
  2. 使用BloomFilter,相当于在查询缓存之前先在集合中查询key是否存在,如果不存在就直接返回
    • *

缓存雪崩

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

解决方案

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

缓存击穿

缓存雪崩的一种,雪崩是多个key失效,击穿是指某个key失效,同一时刻,大量的相同请求会直接打到数据库。

解决方案

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

public List getData() throws InterruptedException {
    List result = new ArrayList();
    // 从缓存读取数据
    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;
}

你可能感兴趣的:(缓存)