缓存穿透
缓存和数据库均不存在(申请打到缓存,未查问到,接着查询数据库,也没有查到)时,大量并发会对数据库造成极大压力。
解决方案
- 设置一个 key-null 的缓存,并将生效工夫能够设置短一点(比方 30s), 这样雷同申请就不会间接打到数据库。
- 应用 BloomFilter,相当于在查问缓存之前先在汇合中查问 key 是否存在,如果不存在就间接返回
-
- *
缓存雪崩
同一时刻大量缓存生效,导致申请全部打到数据库。
解决方案
- 缓存数据的过期工夫设置随机,避免同一时间大量数据过期景象产生
- 如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中
- 设置热点数据永不过期
-
- *
缓存击穿
缓存雪崩的一种,雪崩是多个 key 生效,击穿是指某个 key 生效,同一时刻,大量的雷同申请会间接打到数据库。
解决方案
- 设置热点数据永不过期。
- 采纳互斥锁
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;
}