redis缓存穿透、击穿、雪崩

一、缓存穿透

  当客户端查询一个数据,发现redis内存数据库没有,也就是缓存没有命中。于是向持久层数据库查询,发现也没有,出于容错考虑,本次查询不写入缓存。当用户很多的时候,缓存都没有命中,于是都去请求了持久层数据库。这会给持久层数据库造成很大的压力,这时候就出现了缓存穿透。

  解决方案:

  1、布隆顾虑器(布隆过滤器可以用于检索一个元素是否在一个集合中)

  首先也是对所有可能查询的参数以hash形式存储,当用户想要查询的时候,使用布隆过滤器发现不在集合中,就直接丢弃,不再对持久层查询。

  2、设置默认值

  当存储层不命中后,即使返回的空对象也将其缓存起来,同时会设置一个过期时间,时间很短,几分钟。之后再访问这个数据将会从缓存中获取,保护了后端数据源。

  但是这种方法会存在两个问题:

  (1)如果空值能够被缓存起来,这就意味着缓存需要更多的空间存储更多的键,因为这当中可能会有很多的空值的键;

  (2)即使对空值设置了过期时间,还是会存在缓存层和存储层的数据会有一段时间窗口的不一致,这对于需要保持一致性的业务会有影响。

 

二、缓存雪崩

  缓存雪崩是指,缓存层出现了错误,例如数据未加载到缓存中,或者缓存同一时间大面积失效。于是所有的请求都会达到存储层,存储层的调用量会暴增,导致数据库CPU和内存负载过高,甚至宕机。

比如一个雪崩的简单过程:

1、redis集群大面积故障

2、缓存失效,但依然大量请求访问缓存服务redis

3、redis大量失效后,大量请求转向到mysql数据库

4、mysql的调用量暴增,很快就扛不住了,甚至直接宕机

5、由于大量的应用服务依赖mysql和redis的服务,这个时候很快会演变成各服务器集群的雪崩,最后网站彻底崩溃。

  解决方案:

       (1)redis高可用

  搭建高可用的redis集群,防止缓存大面积故障。

      (2)缓存大面积失效

       避免缓存设置相近的有效期;为有效期增加随机值;统一规划有效期,失效时间均匀分布。

 

三、缓存击穿

  缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,这里的key是某一个key(缓存雪崩是指多个key)。

  解决方案:     

   1、使用分布式缓存支持的互斥锁(mutex key),去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存,也就是load DB 只会一个线程处理;(缺点:代码复杂度增大、存在死锁的风险、存在线程池阻塞的风险)

     2、通过synchronized+双重检查机制:某个key只让一个线程查询,阻塞其它线程;(缺点:会阻塞其他线程)
     3、设置热点数据永不过期;
  (1) redis不设置过期时间,保证了redis层次的时间性。
  (2) 把过期时间设置到key对应的value里面,对即将过期的key,进行一个后台异步线程的缓存构建。


  

 

posted @ 2020-08-19 15:27  西院小人物  阅读(200)  评论(0编辑  收藏  举报