SpringBoot+Redis布隆过滤器防恶意流量击穿缓存的方法


本篇内容介绍了“SpringBoot+Redis布隆过滤器防恶意流量击穿缓存的方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!假设我们的Redis里存有一组用户的注册email,以email作为Key存在,同时它对应着DB里的User表的部分字段。一般来说,一个合理的请求过来我们会先在Redis里判断这个用户是否是会员,因为从缓存里读数据返回快。如果这个会员在缓存中不存在那么我们会去DB中查询一下。现在试想,有千万个不同IP的请求(不要以为没有,我们就在2018年和2019年碰到了,因为攻击的成本很低)带着Redis里根本不存在的key来访问你的网站,这时我们来设想一下:请求到达Web服务器;请求派发到应用层->微服务层;请求去Redis捞数据,Redis内不存在这个Key;于是请求到达DB层,在DB建立connection后进行一次查询千万乃至上亿的DB连接请求,先不说Redis是否撑的住DB也会被瞬间打爆。这就是“Redis穿透”又被称为“缓存击穿”,它会打爆你的缓存或者是连DB一起打爆进而引起一系列的“雪崩效应”。那就是使用布隆过滤器,可以把所有的user表里的关键查询字段放于Redis的bloom过滤器内。有人会说,这不疯了,我有4000万会员?so what!你把4000会员放在Redis里是比较夸张,有些网站有8000万、1亿会员呢?因此我没让你直接放在Redis里,而是放在布隆过滤器内!布隆过滤器内不是直接把key,value这样放进去的,它存放的内容是这么一个样的:BloomFilter是一种空间效率的概率型数据结构,由Burton Howard Bloom 1970年提出的。通常用来判断一个元素是否在集合中。具有极高的空间效率,但是会带来假阳性(False positive)的错误。False positive&&False negatives
由于BloomFiter牺牲了一定的准确率换取空间效率。所以带来了False positive的问题。False positive
BloomFilter在判断一个元素在集合中的时候,会出现一定的错误率,这个错误率称为False positive的。通常缩写为fpp。False negatives
BloomFilter判断一个元素不在集合中的时候的错误率。 BloomFilter判断该元素不在集合中,则该元素一定不再集合中。故False negatives概率为0。BloomFilter使用长度为m bit的字节数组,使用k个hash函数,增加一个元素: 通过k次hash将元素映射到字节数组中k个位置中,并设置对应位置的字节为1。
查询元素是否存在: 将元素k次hash得到k个位置,如果对应k个位置的bit是1则认为存在,反之则认为不存在。由于它里面存的都是bit,因此这个数据量会很小很小,小到什么样的程度呢?在写本博客时我插了100万条email信息进入Redis的bloom filter也只占用了3Mb不到。Bloom Filter会有几比较关键的值,根据这个值你是大致可以算出放多少条数据然后它的误伤率在多少时会占用多少系统资源的。这个算法有一个网址:https://krisives.github.io/bloom-calculator/,我们放入100万条数据,假设误伤率在0.001%,看,它自动得出Redis需要申请的系统内存资源是多少?那么怎么解决这个误伤率呢?很简单的,当有误伤时业务或者是运营会来报误伤率,这时你只要添加一个小白名单就是了,相对于100万条数据来说,1000个白名单不是问题。并且bloom filter的返回速度超块,80-100毫秒内即返回调用端该Key存在或者是不存了。假设我用python爬虫爬了4亿条url,需要去重?看,布隆过滤器就是用于这个场景的。下面就开始我们的Redis BloomFilter之旅。Redis从4.0才开始支持bloom filter,因此本例中我们使用的是Redis5.4。Redis的bloom filter下载地址在这:https://github.com/RedisLabsModules/redisbloom.git让Redis启动时可以加载bloom filter有两种方式:手工加载式:每次启动自加载:编辑Redis的redis.conf文件,加入:Like this:基本指令:bf.reserve {key} {error_rate} {size}上面这条命令就是:创建一个空的布隆过滤器,并设置一个期望的错误率和初始大小。{error_rate}过滤器的错误率在0-1之间,如果要设置0.1%,则应该是0.001。该数值越接近0,内存消耗越大,对cpu利用率越高。bf.add {key} {item}上面这条命令就是:往过滤器中添加元素。如果key不存在,过滤器会自动创建。bf.exists {key} {item}上面这条命令就是:判断指定key的value是否在bloomfilter里存在。存在:返回1,不存在:返回0。网上很多写的都是要么是直接使用jedis来操作的,或者是java里execute一个外部进程来调用Redis的bloom filter指令的。很多都是调不通或者helloworld一个级别的,是根本无法上生产级别应用的。笔者给出的代码保障读者完全可用!笔者不是数学家,因此就借用了google的guava包来实现了核心算法,核心代码如下:BloomFilterHelper.java下面放出全工程解说,我已经将源码上传到了我的git上了,确保读者可用,源码地址在这:https://github.com/mkyuangithub/mkyuangithub.git项目Redis配置我们在redis-practice工程里建立一个application.properties文件,内容如下:以上这个是demo环境的配置。我们此处依免费云主机域名旧使用的是在前一篇springboot+nacos+dubbo实现异常统一管理中的xxx-project->sky-common->nacos-parent的依赖结构。在redis-practice工程的org.sky.config包中放入redis的springboot配置RedisConfig.java这个配置除实现了springboot自动发现redis在application.properties中的配置外我们还添加了不少redis基本的数据结构的操作的封装。我们为此还要再封装一套Redis Util小组件,它们位于sky-common工程中RedisUtil.javaRedisKeyUtil.java然后就是制作 redis里如何使用BloomFilter的BloomFilterHelper.java了,它也位于sky-common文件夹,源码如上已经贴了,因此此处就不再作重复。最后我们在sky-common里放置一个UserVO用于演示UserVO.java下面给出我们所有gitrepo里依赖的nacos-parent的pom.xml文件内容,此次我们增加了对于“spring-boot-starter-data-redis”,它跟着我们的全局springboot版本走:parent工程的pom.xml

相关推荐: Git如何修改最近一个commit

这篇文章主要介绍了Git如何修改最近一个commit,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。commit完发现有一些临时的log忘记去掉?有一些文免费云主机域名件忘记添加?commit信息…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 03/31 18:50
下一篇 03/31 20:36

相关推荐