高并发问题,通常会有缓存穿透、缓存击穿、缓存雪崩
缓存穿透
是指查询一个本身不存在的数据,绕过了缓存一直查数据库,容易造成数据库性能下降,解决方案是给数据库查询不到的key,也设置一个空值进行缓存,过期时间可以设置小一些。
另外一种解决方案:
单机模式下:使用google布隆过滤器工具包
https://blog.csdn.net/fouy_yun/article/details/81075432
分布式模式下:使用redis的布隆过滤器模块
https://www.cnblogs.com/happydreamzjl/p/11834277.html
缓存雪崩
缓存雪崩,是指在某一个时间段,缓存集中过期失效。
产生雪崩的原因之一,比如在写本文的时候,马上就要到双十二零点,很快就会迎来一波抢购,这波商品时间比较集中的放入了缓存,假设缓存一个小时。那么到了凌晨一点钟的时候,这批商品的缓存就都过期了。而对这批商品的访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰。
缓存击穿
是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。
private Lock lock = new ReentrantLock();
public String getValue() {
String key = "key";
String value = RedisUtils.get(key);
if(value == null) {
try {
lock.lock(); // 防缓存击穿
value = RedisUtils.get(key);
if(value == null) { // 双重判断,不然等待锁上的线程会继续查数据库
value = Dao.get(); // 查询数据库
if(value == null) { // 防缓存穿透
RedisUtils.setnx(key, "","2分钟");
} else {
RedisUtils.setnx(key, value, "半小时"+随机数); // 防缓存雪崩
}
}
} catch (Exception e) {
} finally {
lock.unlock();
}
}
return value;
}