用户请求的缓存正常流程图
上图是一个正常的简单的缓存流程!!!
土豆用户去访问某宝,某宝请求redis看看缓存中有没有土豆用户请求的数据,
如果redis中有该数据的缓存,则直接返回数据展示出来供应用户的需求,
如果redis中没有该用户请求的数据,redis就会做一件事,去数据库中进行查找,数据库中查到值了之后做两件事情,第一件事:把数据返回到redis缓存中。第二件事:把查询到的数据返回到某宝*用户的需求
缓存雪崩:
举个例子:用户在双十二的时候,想去某宝抢购商品,用户点进去进入首页展示出了各种各样的商品,这些商品大部分都是缓存在redis中,对应了着很多key,加入这些key的缓存时间是三个小时或者四个小时,当缓存时间已过,缓存失效,导致大量的用户把请求打到了数据库中,数据库承载不了,导致数据库挂掉,就像大大的雪山峰突然崩塌了。
列举四种解决方法:
第一种:设置这个缓存的失效时间,让它不要在同一时间失效,设置缓存时间时随机初始化缓存的时间,这样就避免了同一时间失效
第二种:搭建redis集群,把热点的key分布在不同的redis集群上面
第三种:不设置缓存失效的时间
第四种:设置一个定时的任务,定时刷这个缓存的时间
缓存穿透:
举个例子:比如说土豆开发了一个网站,异常的火爆男女老少该来的也来了不该来的也来了,同行一看眼红了,这不行要安排土豆,然后同行就想起来了,redis缓存中的key都是没有负数,如果用负数请求redis缓存中没有就可以直接将请求发送到数据库中,同行就利用这一个特点故意请求缓存中不存在的数据,写了几个循环大量发送key为-1或者负数,等等,导致redis缓存中没有该数据,把redis穿透了请求到了数据库,数据库一时间接收到了大量请求,又导致数据库崩了。
解决方案:
第一种就是:请求的数据穿透到数据库,无论数据库里面有没有值都把参数信息缓存到redis中,下一次再请求可以让redis缓存拦截处理一下。但是下一次可能同行就用另外一个参数来访问,只能说治标不治本
第二种就是:把恶意请求的用户ip拉黑了,但可能会换另外一个ip,同样治标不治本
第三种就是:可以对象请求参数的合法性进行校验,如果不合法直接return掉
第四种就是:用到一种布隆过滤器
缓存击穿:
再举个例子:过双十一,老马把珍藏多年的老北京布鞋拿出来拍卖,大家伙一看是老马穿过的老北京想缅怀一下老马的成功之路,程序员按照老马的指示也是安排上架了,好家伙老北京布鞋一下子被拍卖了四个小时,老北京布鞋的数据在redis缓存中时长是四个半小时,又拍卖了一会,redis缓存中老北京失效了,用户的大量请求一瞬间又达到了数据库中,数据库又承载不了挂掉了,老马不高兴了,也是很成功的把程序员送到了非洲给自己挖煤了
解决方案:
1,那就是缓存时间不过期,那肯定不太好
2,采用互斥锁,在请求到数据库这一步中上个锁,大量请求进来只有一个线程抢到了锁,进入数据库查到数据并返回给redis中,其他没有抢到的就线程就休眠几秒,过了几秒之后让其他线程去redis中查找数据,这样就降低了了数据库请求量大的问题!!