小王
文章8
标签3
分类5
redis缓存雪崩、穿透、击穿

redis缓存雪崩、穿透、击穿

正常缓存流程

用户访问某宝,然后某宝去访问redis如果redis有这个数据就返回回去显示出来,如果没有它就会去请求mysql如果mysql查到数据后就会把查到的数据同步到redis中,同时把数据返回给某宝。

问题

缓存雪崩

大量的redis缓存在同一时间失效,导致大量请求打到mysql造成数据库响应不及时挂掉

解决方案:

  1. 设置缓存失效时间让它不要在同一时间失效,在设置缓存的时候随机初始化失效时间,这样的话所有的缓存就不会同一时间失效打所有请求打到数据库上
  2. 还有这个redis一般是集群部署,我们把热点的key放到不同的节点上去,让这些热点的缓存平均的分布在这个不同的redis节点上
  3. 还有就是最暴力的方法就是不设置这个缓存失效的时间让它永远不失效
  4. 还有就是去跑这个定时任务,让他去定时的刷这个缓存,比如说我这个缓存设置了三个小时失效那么我在失效之前就把这个redis缓存给他重新跑进去然后在设置三小时不断的用这个定时任务去刷新这个缓存,这个缓存就不会失效了

缓存穿透

是指redis缓存和数据库都没有这样的数据,一般出现这样的情况都不是正常用户,是一些恶意用户。

解决方案:

  1. 如果请求穿过redis直接到数据库,我数据库无论查出什么结果是空还是有值,都缓存到redis里面,这样他下次用同一个参数发起请求就不会穿透redis,但是他可能会换不同的参数。
  2. 就会将他的ip拉黑,但是他也会换不同的ip
  3. 就是将参数进行合法性校验,在判断这个参数不合法的时候,直接return掉
  4. 使用布隆过滤器

缓存击穿

当大量的用户请求去访问某个热点的key,当这个热点的key突然失效把请求打到数据库上,这个过程就叫做缓存的击穿。

解决方:

  1. 让这个缓存永远不过期,但这个方案肯定不太好
  2. 使用分布式锁,如果是单体应用就可以使用互斥锁。

原理就是:首先大量的用户去访问这个redis是请求数据,如果有的话就返回给用户,如果redis里面的数据为空的话,他就会去请求数据库。我们就在请求数据库这步给他上上锁,那么这个时候只有一个线程能抢到这个锁,所以也就只有一个线程能操作这个数据库,那么这个时候对数据库的压力就非常小,当他查询到这个数据后呢,在把这个缓存写到redis里去,其他没有抢到锁的线程让他先睡几毫米,然后让他重新去redis里面去查询。因为我们有一个线程抢到了这个锁,去数据库里查到数据并把数据放到redis里面去,那么其他线程去访问redis的时候,这个redis里面就有数据的。可以用zookeeper实现,还可以redis实现

本文作者:小王
本文链接:https://wswle.cn/20201007.html
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可
×