一、缓存雪崩
1.1 缓存雪崩是因为原有缓存失效(过期),新缓存未到期间。一切恳求都去查询数据库,而对数据库CPU和内存形成巨大压力,严重的会形成数据库宕机。然后形成一系列连锁反应,形成整个系统崩溃。A8站源码交易平台
因为缓存层承载了很多的恳求,有效的维护了存储 层,可是假如缓存因为某些原因,全体不能够提供服务,所以一切的恳求,就会到达存储层,存储层的调用量就会暴增,形成存储层也会挂掉的状况。缓存雪崩的英文解说是奔逃的野牛,指的是缓存层当掉之后,并发流量会像奔腾的野牛一样,很多后端存储,雪崩描述的是一连串的负面呼应,如下图:
1.2 存在这种问题的一个场景是:当缓存服务器重启或者很多缓存集中在某一个时刻段失效,这样在失效的时候,很多数据会去直接拜访DB,此刻给DB很大的压力。A8站源码交易平台
1.3.处理方法
(1)设置redis集群和DB集群的高可用,假如redis呈现宕机状况,能够立即由别的机器代替上来。这样能够防止一部分的危险。
(2)使用互斥锁
在缓存失效后,经过加锁或者队列来操控读和写数据库的线程数量。比如:对某个key只允许一个线程查询数据和写缓存,其他线程等候。单机的话,能够使用synchronized或者lock来处理,假如是散布式环境,能够是用redis的setnx指令来处理。
(3)不同的key,能够设置不同的过期时刻,让缓存失效的时刻点不一致,尽量到达平均散布。
(4)永久不过期
redis中设置永久不过期,这样就确保了,不会呈现热点问题,也就是物理上不过期。
(5)资源维护
使用netflix的hystrix,能够做各种资源的线程池隔离,然后维护主线程池。
二、缓存穿透
2.1 缓存穿透是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后回来空。这样恳求就绕过缓存直接查数据库,这也是经常提的缓存命中率问题A8站源码交易平台
2.2 形成的原因:
2.1.1 业务自身代码或数据呈现问题;
2.2.1 一些恶意攻击、爬虫形成很多空的命中,此刻会对数据库形成很大压力。
2.3 处理方法
2.3.1 设置布隆过滤器,将一切或许存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,
从避免了对底层存储系统的查询压力。
2.3.2 假如一个查询回来的数据为空,不管是数据不存在还是系统故障,我们仍然把这个结果进行缓存,可是它的过期时刻会很短
最长不超过5分钟,这样第二次到缓冲中获取就有值了,而不会继续拜访数据库,这种方法最简略粗暴 代码大致逻辑如下:
public String getCacheValue(){
int cacheTime = 30;
String cacheKey = "product_list";
String cacheValue = redisUtil.get(cacheKey);
if (StringUtils.isNotBlank(cacheValue)) {
return cacheValue;
}else{
cacheValue = getListFromDB(); //数据库查询不到,为空。
if (StringUtils.isBlank(cacheValue)) {
cacheValue = ""; //假如发现为空,设置个默认值,也缓存起来。
}
redisUtil.Add(cacheKey, cacheValue, cacheTime);
return cacheValue;
}
return "";
}
这样把空结果也给缓存起来,这样下次相同的恳求就能够直接回来空了,即能够避免当查询的值为空时引起的缓存穿透。一起也能够独自设置个缓存区域存储空值,对要查询的key进行预先校验,然后再放行给后面的正常缓存处理逻辑。
