Redis缓存三大问题及解决方案

Redis缓存三大问题

学过Redis的童鞋们应该都听说过Redis缓存的三大问题,穿透、雪崩、击穿,但是可能对这几个词没有什么概念,也没有去深入理解,下面就简单的介绍一下Redis经常提到的三大问题,和三大问题的解决方法。

缓存穿透

我们都知道Redis是一款功能非常强大的NoSql数据库,是基于内存存储的数据库软件,在实际开发中经常被用作缓存,临时存储数据。使用Redis主要是为了分担数据库的压力和临时存储一些供不同进程可以共享使用的数据。

项目执行流程:

  1. 用户发起请求
  2. nginx通过反向代理将请求转发至tomcat
  3. tomcat去redis查询数据,如果redis存在请求需要的数据则返回,如果redis中不存在,则去数据库查询
  4. 从数据库中查询到的数据返回给tomcat的同时也将查到的数据放入redis,供下次访问使用。
    Redis缓存三大问题及解决方案_第1张图片

按照这个流程redis是可以正常的为数据库分担压力的,但是不是所有的用户都是正人君子,总有小人会想办法破坏你的项目,击垮你的数据库。
这些小人会利用漏洞绕过你的redis直接访问你的数据库,并且不断发送数据去攻击数据库。最终造成数据库被打死。
例如,数据库的id是自增长的,所有的键都大于0,此时如果小人传入的参数是-1,这个-1是不可能在数据库中存在的,那么服务器接到请求后会先向redis中查询,结果必然是不存在的,然后程序会访问数据库,数据库会返回null值,并且不会进入redis缓存,那么小人就会利用这个漏洞绕过redis对数据库不停发出请求,对数据库造成压力,最终打死数据库。

为了避免有人利用这个漏洞恶意攻击我们的数据库,我们可以采取以下几种措施:

  1. 在服务器接口中增加校验,对传入的参数进行校验,不合法的直接return,比如查询id<=0的直接拦截,在根源上避免用户的非法请求去访问数据库。但是依旧存在问题,如果用户访问的是合法数据,但是数据库依旧不存在,那么还是会绕过
  2. 如果从数据库查询的结果为null,也放入缓存,key就是用户提交的主键,value是null,只是设定的缓存声明周期时间较短,比如设置为30秒或60秒。这样下次用户再根据这个key查询redis就可以查询到值了(虽然为null),从而在一定程度上保护我们的数据库受到攻击。
  3. 在程序启动时,就将数据库中的数据全量放入redis,并且设置redis中的缓存数据为永不过期,并且引入布隆过滤器,利用布隆过滤器高效的数据结构和算法快速判断出这个key是否存在在redis中,在用户发送请求的时候,先去布隆过滤器进行查找,如果redis中存在则查询redis,如果redis中不存在,则直接return。

缓存雪崩

缓存雪崩指的是在程序运行的某一时间段,redis中缓存集体失效,如果是像双十一这种大型秒杀活动,在缓存失效的一瞬间,所有用户的请求都直接落在了数据库上,数据库直接就被高并发的访问直接打死。哪怕是重启数据库,也会在启动的一瞬间瞬间被打死。所以缓存在一个时间段内大面积失效,那一瞬间数据库直接暴露给用户,这将是毁灭性的打击。

解决方法:

  1. 把每个key的失效时间都加个随机值,这样保证不会出现大面积的缓存失效。
  2. 可以预见性的提前将redis中的key设置成永不过期,比如说在双十一前夕将大量和活动相关的数据提前放入redis中,并将key设置为长期有效,等经过双十一后,在将缓存数据进行分批销毁。
  3. 搭建redis集群保证redis的高可用,将热点数据分片部署在不同的redis中,防止key在一定时间内大面积失效。

缓存击穿

缓存击穿在名字上和缓存穿透有点像,也是初学者容易弄混的一点。但是这两个本质上还是不一样的。
缓存击穿指的是redis缓存中某一个热点key不停的扛着高并发的访问,比如双十一的秒杀,大量的用户请求都落在同一个key上,在这个key失效的瞬间,用户请求直接打入数据库中,就像在redis上凿穿一个洞一样。

解决办法:

  1. 将热点数据设置为永不过期。
    这样就可以直接避免缓存击穿的问题了。

你可能感兴趣的:(redis,redis,缓存)