Redis布隆过滤器原理与实践

Redis布隆过滤器原理与实践背景在高并发请求时,业务数据一般会对数据进行缓存,提高系统并发量,因为磁盘IO和网络IO相对于内存IO的成百上千倍的性能劣势。做个简单计算,如果我们需要某个数据,该数据从数据库磁盘读出来需要0.1s,从交换机传过来需要0.05s,那么每个请求完成最少0.15s(当然,事实上磁盘和网络IO也没有这么慢,这里只是举例),该数据库服务器每秒只能响应67个请求;而如果该数据存在于本机内存里,读出来只需要10us,那么每秒钟能够响应100,000个请求。通过将高频使用的数据存在离cpu更近的位置,以减少数据传

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

背景

在高并发请求时,业务数据一般会对数据进行缓存,提高系统并发量,因为磁盘IO和网络IO相对于内存IO的成百上千倍的性能劣势。 做个简单计算,如果我们需要某个数据,该数据从数据库磁盘读出来需要0.1s,从交换机传过来需要0.05s,那么每个请求完成最少0.15s(当然,事实上磁盘和网络IO也没有这么慢,这里只是举例),该数据库服务器每秒只能响应67个请求;而如果该数据存在于本机内存里,读出来只需要10us,那么每秒钟能够响应100,000个请求。 通过将高频使用的数据存在离cpu更近的位置,以减少数据传输时间,从而提高处理效率,这就是缓存的意义。

cache

但是在上文中提到过,缓存会存在击穿,穿透等问题,对于此我们可以引入Bloom Filter (布隆过滤器),防止数据库压力过大导致系统异常。

Bloom Filter

如果想要判断一个元素是不是在一个集合里,一般想到的是将所有元素保存起来,然后通过比较确定。 链表,树等等数据结构都是这种思路. 但是随着集合中元素的增加,我们需要的存储空间越来越大, 检索速度也越来越慢(O(n),O(logn))。

不过还有一种叫作散列表(又叫哈希表,Hash table)的数据结构,它可以通过一个Hash函数将一个 元素映射成一个位阵列中的一个点,这样一来,我们只要看看这个点是不是1就可以知道集合中有没有它了。 这就是布隆过滤器的基本思想。

布隆过滤器(Bloom Filter) 是 1970 年由布隆提出的。它 实际上 是一个很长的二进制向量和一系列 随机映射函数 ,实际上你也可以把它简单理解为一个不怎么精确的 set 结构,当你使用它的 contains 方法判断某个对象是否存在时,它可能会误判。但是布隆过滤器也不是特别不精确,只要参数设置的合理, 它的精确度可以控制的相对足够精确,只会有小小的误判概率。

当布隆过滤器说某个值存在时,这个值 可能不存在;当它说不存在时,那么 一定不存在。打个比方,当它说 不认识你时,那就是真的不认识,但是当它说认识你的时候,可能是因为你长得像它认识的另外一个朋友 (脸长 得有些相似),所以误判认识你。

原理

当一个元素加入布隆过滤器中的时候,会进行如下操作:

  1. 使用布隆过滤器中的哈希函数对元素值进行计算,得到哈希值(有几个哈希函数得到几个哈希值)。
  2. 根据得到的哈希值,在位数组中把对应下标的值置为 1。

当我们需要判断一个元素是否存在于布隆过滤器的时候,会进行如下操作:

  1. 对给定元素再次进行相同的哈希计算;
  2. 得到值之后判断位数组中的每个元素是否都为 1,如果值都为 1,那么说明这个值在布隆过滤器中,

如果存在一个值不为 1,说明该元素不在布隆过滤器中。

bloom_1

如上图,

  1. 有8个hash位,且默认值为0,
  2. 当对tencent进行散列hash之后,2,5,7位被置为1,
  3. 继续对cloud进行散列hash后,3,4,6位被置为1。
  4. 这时候我们再对其它词汇other进行hash,假设散列为1、2、3,1位为0,可以判断该单词不存在集合中。

汇总流程 bloom_2

如何选择哈希函数个数和布隆过滤器长度

如果布隆过滤器的长度太小,所有的 bit 位很快就会被用完,此时任何查询都会返回“可能存在”; 如果布隆过滤器的长度太大,那么误判的概率会很小,但是内存空间浪费严重。 类似的,哈希函数的个数越多,则布隆过滤器的 bit 位被占用的速度越快;哈希函数的个数越少, 则误判的概率又会上升。因此,布隆过滤器的长度和哈希函数的个数需要根据业务场景来权衡。

三个参数

  • 哈希函数的个数k;
  • 布隆过滤器位数组的容量m;
  • 布隆过滤器插入的数据数量n;

关于三个值的设定,有位大佬十年前的文章已经做了总结,需要深厚的数学功底,这里不再详细赘述。 文章链接是http://blog.csdn.net/jiaomeng/article/details/1495500

主要的数学结论有:

  • 为了获得最优的准确率,当k = ln2 * (m/n)时,布隆过滤器获得最优的准确性;

优缺点

优点:优点很明显,二进制组成的数组,占用内存极少,并且插入和查询速度都足够快。

缺点:随着数据的增加,误判率会增加;还有无法判断数据一定存在;另外还有一个重要缺点,无法删除数据

场景

  • 大数据判断是否存在:这就可以实现出上述的去重功能,如果你的服务器内存足够大的话,那么使用 HashMap 可

能是一个不错的解决方案,理论上时间复杂度可以达到 O(1)的级别,但是当数据量起来之后,还是只能考虑布隆过滤器。

  • 解决缓存穿透(背景中提到的问题):利用布隆过滤器我们可以预先把数据查询的主键,比如用户 ID 或文章 ID

缓存到过滤器中。当根据 ID 进行数据查询的时候,我们先判断该 ID 是否存在,若存在的话,则进行下一步处 理。若不存在的话,直接返回,这样就不会触发后续的数据库查询。需要注意的是缓存穿透不能完全解决,我们只 能将其控制在一个可以容忍的范围内。

  • 爬虫/ 邮箱等系统的过滤:平时不知道你有没有注意到有一些正常的邮件也会被放进垃圾邮件目录中,这就是使用布隆过滤器 误判 导致的。
  • Google Chrome 使用布隆过滤器识别恶意 URL。

基本操作

布隆过滤器有两个基本指令,bf.add 添加元素,bf.exists 查询元素是否存在, 它的用法和 set 集合的 saddsismember 差不多。注意 bf.add 只能一次添加一个元素, 如果想要一次添加多个,就需要用到 bf.madd 指令。同样如果需要一次查询多个元素是否存在, 就需要用到 bf.mexists 指令。

127.0.0.1:6379> bf.reserve users 0.01 1000
OK
127.0.0.1:6379> bf.add users u1
(integer) 1
127.0.0.1:6379> bf.add users u2
(integer) 1
127.0.0.1:6379> bf.add users u3
(integer) 1
127.0.0.1:6379> bf.exists users u3
(integer) 1
127.0.0.1:6379> bf.madd users user4 user5 user6
1) (integer) 1
2) (integer) 1
3) (integer) 1
127.0.0.1:6379> bf.mexists users user4 user5 user6 user7
1) (integer) 1
2) (integer) 1
3) (integer) 1
4) (integer) 0
复制代码

bf.reserve 有三个参数,分别是 key、error_rate (错误率) 和 initial_size:

error_rate 越低,需要的空间越大,对于不需要过于精确的场合,设置稍大一些也没有关系, 比如上面说的推送系统,只会让一小部分的内容被过滤掉,整体的观看体验还是不会受到很大影响的;

initial_size 表示预计放入的元素数量,当实际数量超过这个值时,误判率就会提升,所以需要 提前设置一个较大的数值避免超出导致误判率升高;

如果不适用 bf.reserve,默认的 error_rate0.01,默认的 initial_size100

作者:merlinfeng
 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/185030.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 地理加权回归模型步骤_地理加权回归中的拟合度

    地理加权回归模型步骤_地理加权回归中的拟合度目录数据准备加载需要的R包导入空间数据空间自相关分析空间邻域面数据空间邻域点数据空间邻域全局空间自相关局部空间自相关空间回归分析线性回归分析地理加权回归经典的线性回归模型是建立在最小二乘法(OLS模型)基础上对参数进行“平均”或“全局”估计。如果自变量为空间数据,且自变量间存在空间自相关性,传统回归模型(OLS模型)残差项独立的假设将无法满足。地理加权回归(GWR)模型能够反映参数在不同空间的空间非平稳性,使变量间的关系可以随空间位置的变化而变化,其结果更符合客观实际,能反映局部情况。杨晴青,刘倩

  • goland 激活码2021.5[在线序列号]

    goland 激活码2021.5[在线序列号],https://javaforall.cn/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

  • oracle游标的使用详解_oracle游标失效

    oracle游标的使用详解_oracle游标失效1、游标的概念游标(CURSOR):游标是把从数据表中提取出来的数据,以临时表的形式存放在内存中,在游标中有一个数据指针,在初始状态下指向的是首记录,利用fetch语句可以移动该指针,从而对游标中的数据进行各种操作。2、游标的作用游标是用来处理使用SELECT语句从数据库中检索到的多行记录的工具。借助于游标的功能,数据库应用程序可以对一组记录逐条进行处理,每次处理一行。3、游标的类型…

    2022年10月25日
  • 百度分享按钮代码

    百度分享按钮代码百度分享官网已经获取不了了,但是这些按钮功能还在.下面直接把代码放出,有需要的同学可以直接复制第一种:按钮式:<divclass=”bdsharebuttonbox”><ahref=”#”class=”bds_more”data-cmd=”more”></a><ahref=”#”class=”bds_qzone”…

  • linux hexdump命令_hexdump用法

    linux hexdump命令_hexdump用法Linux中hexdump命令简介hexdump主要用来查看“二进制”文件的十六进制编码。*注意:它能够查看任何文件,不限于与二进制文件。*语法hexdump[选项][文件]…选项-nlength:格式化输出文件的前length个字节-C:输出规范的十六进制和ASCII码-b:单字节八进制显示-c:单字节字符显示-d:双字节十进制显示-o:双字节八进制显示-…

  • 基于支持向量机的手写数字识别详解(MATLAB GUI代码,提供手写板)

    基于支持向量机的手写数字识别详解(MATLAB GUI代码,提供手写板)摘要:本文详细介绍如何利用MATLAB实现手写数字的识别,其中特征提取过程采用方向梯度直方图(HOG)特征,分类过程采用性能优异的支持向量机(SVM)算法,训练测试数据集为学术及工程上常用的MNIST手写数字数据集,博主为SVM设置了合适的核函数,最终的测试准确率达99%的较高水平。根据训练得到的模型,利用MATLABGUI工具设计了可以手写输入或读取图片进行识别的系统界面,同时可视化图片处理过程及识别结果。本套代码集成了众多机器学习的基础技术,适用性极强(用户可修改图片文件夹实现自定义数据集训练)。

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号