“Redis缓存穿透”规避方案

2019-08-23  本文已影响0人  程序员网址导航

Redis被应用于缓存


Redis作为当前一个非常热门的NoSQL,也被频繁应用在多个场景下,比如被作为缓存来减少DB的负载;分布式环境下分布式锁的应用;全局唯一ID实现方案之一;还有人利用Redis的List数据类型实现消息队列……

下图是一个Redis被用作缓存,以减小DB负载,通过对内存的高效利用来提升系统的并发度的一个简单的场景。

过程简述:系统接受到数据查询请求后,先去查询Redis,如果Redis命中了,则直接将Redis的查询结果返回;如果Redis没有命中,紧接着去查询DB,最后将DB查询结构返回;

image.png

这个设计直接、简单,并且多数情况下直接这样使用也不会有问题的。

缓存穿透的原理

如上图所示,缓存就像是数据库的一道防火墙,将请求频繁的数据放入到缓存,可以减轻数据库的访问压力。但是如果有人想要恶意攻击,其实是很容易穿透现有的缓存。比如我们的redis key的生产规则是这样子的,客户code+“_”+业务编号(其中业务编号可能是直接利用UUID生成的一个32位长度字符串)。

image.png

一般情况下我们API调用都会在网关层做客户code校验,判断当前code是否合法,或者会有流量校验等拦截逻辑。但是如果别人知道了我们的code,使用一个简单的缓存key来一直查我们的接口("code_111"),这种情况下因为code已经通过了我们的客户code校验,所以请求会直接查缓存,但是这个查询的key一定是不在缓存中的,所以每次都次查询DB,相当于多有的请求都会打到DB上。缓存形同虚设,很容易把库搞挂,这个问题被称为”缓存穿透“

image.png

可能导致缓存穿透的几个原因


1.就像上面说了,攻击者猜中你的缓存key生成规则,或者就拿一个不合法的key来一直查你的接口;
2.第一次数据访问,缓存中没有数据,大并发下所有的请求都会打的库上;
3.数据库的数据也是空的,即使访问了数据库,也是没有数据,那缓存中自然也没有数据;

解决缓存穿透的方案


其实最简单的便是针对可能导致缓存穿透的原因逐一规避:

image.png

第一步:在服务启动之前,先将我们可以预测到的可能会被频繁访问的热点数据导入到缓存;

第二步:在命中缓存之前,可以根据我们缓存中key的生成规则做一次简单的规则校验。比如我们的key应该是 code_32为长度的字符串,但是当前的请求key的code_不满足32位长度字符串格式可以直接拒绝掉。

第三步:Synchronized双重检测机制,这时我们需要使用同步机制,在同步代码之前先查一次缓存,看key是否存在,如果不存在在同步代码块里再次查询缓存看是否有key。这样”双重检查的目的“,还是避免并发场景下导致没有意义的数据库查询。

第四步:不管数据库中是否有数据,都在缓存中保存对应的key,值为空就行。–这样是为了避免数据库中没有这个数据,导致的平凡穿透缓存对数据库进行访问。

第五步:第4步中的空值如果太多,也会导致内存耗尽。导致不必要的内存消耗。这样就要定期的清理空值的key。避免内存被恶意占满。导致正常的功能不能缓存数据。

个人网站:relaxheart网

上一篇下一篇

猜你喜欢

热点阅读