1.缓存雪崩
- 同一时间缓存大面积失效,那一瞬间redis相当于没有,比如这个时候有5000个请求过来,本来redis可以抗住4000个请求,但是这个时候缓存失效了,相当于5000个请求直接落实在数据库中。这个时候数据库可能会被当前流量给卡死,宕机了。重启也有可能会被新的流量给卡死。
2.如何解决缓存雪崩
- redis批量存储的时候把每个key的失效时间加上一个随机值。保证不会在容易时间大面积的失效。
- redis集群部署,热点数据均匀分布在不同的redis库中
- 设置热点数据永不过期,有更新直接更新内存
3.缓存穿透
- 缓存穿透指的是 数据库和redis中都没有的数据,用户不断的发送请求会导致数据库压力过大,击垮数据库,例如我们数据库中的id基本都是大于0的。如果一直发送id=-1或者当前id不存在的数值就会出现这种情况。
4.如何解决缓存穿透
- 设置参数校验规则
- boomfilter:原理主要是利用高效的数据结构和算法判断这个key是否存在数据库中,不存在return,存在就查询db刷新kv再return。
5.缓存击穿
- 类似于缓存雪崩,但是又有一点不一样,缓存雪崩是因为大面积的缓存失效打崩了数据库,而缓存击穿是指一个key非常热门,在并的扛着大并发,大并发集中对这个点进行访问,当这个key失效的瞬间,持续的大并发就击穿缓存,直接请求数据库。
6.如何解决缓存击穿
- 热点数据设置永远不过期
- 定时更新热点数据
- 加上互斥锁:多线程下同一时刻只允许一个线程执行
private static Lock reenLock = new ReentrantLock();
public String getData() {
// 从缓存读取数据
String result = getFromCache();
if ( StringUtils.isBlack( result ) ) {
if ( reenLock.tryLock() ) {
try {
// 从数据库查询数据
result = getFromDB();
// 将查询到的数据写入缓存
setCache( result );
} finally {
reenLock.unlock();
}
} else {
// 先查一下缓存
result = getFromCache();
if ( StringUtils.isBlack( result ) ) {
// 休息一会
Thread.sleep( 100L );
// 重试
return getData();
}
}
}
return result;
}