布隆过滤器速度_详解布隆过滤器的原理、使用场景和注意事项

今天碰到个业务,他的 Redis 集群有个大 Value 用途是作为布隆过滤器,但沟通的时候被小怼了一下,意思大概是 “布隆过滤器原理都不懂,还要我优化?”。技术菜被人怼认了、怪不得别人,自己之前确实只是听说过这个,但是没深入了解过,趁这个机会补充一下知识。

在进入正文之前,之前看到的有句话我觉得说得很好:

Data structures are nothing different. They are like the bookshelves of your application where you can organize your data. Different data structures will give you different facility and benefits. To properly use the power and accessibility of the data structures you need to know the trade-offs of using one.

大意是不同的数据结构有不同的适用场景和优缺点,你需要仔细权衡自己的需求之后妥善适用它们,布隆过滤器就是践行这句话的代表。

什么是布隆过滤器

本质上布隆过滤器是一种数据结构,比较巧妙的概率型数据结构(probabilistic data structure),特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”。

相比于传统的 List、Set、Map 等数据结构,它更高效、占用空间更少,但是缺点是其返回的结果是概率性的,而不是确切的。

实现原理

HashMap 的问题

讲述布隆过滤器的原理之前,我们先思考一下,通常你判断某个元素是否存在用的是什么?应该蛮多人回答 HashMap 吧,确实可以将值映射到 HashMap 的 Key,然后可以在 O(1) 的时间复杂度内返回结果,效率奇高。但是 HashMap 的实现也有缺点,例如存储容量占比高,考虑到负载因子的存在,通常空间是不能被用满的,而一旦你的值很多例如上亿的时候,那 HashMap 占据的内存大小就变得很可观了。

还比如说你的数据集存储在远程服务器上,本地服务接受输入,而数据集非常大不可能一次性读进内存构建 HashMap 的时候,也会存在问题。

布隆过滤器数据结构

布隆过滤器是一个 bit 向量或者说 bit 数组,长这样:

image

如果我们要映射一个值到布隆过滤器中,我们需要使用多个不同的哈希函数生成多个哈希值,并对每个生成的哈希值指向的 bit 位置 1,例如针对值 “baidu” 和三个不同的哈希函数分别生成了哈希值 1、4、7,则上图转变为:

image

Ok,我们现在再存一个值 “tencent”,如果哈希函数返回 3、4、8 的话,图继续变为:

image

值得注意的是,4 这个 bit 位由于两个值的哈希函数都返回了这个 bit 位,因此它被覆盖了。现在我们如果想查询 “dianping” 这个值是否存在,哈希函数返回了 1、5、8三个值,结果我们发现 5 这个 bit 位上的值为 0,说明没有任何一个值映射到这个 bit 位上,因此我们可以很确定地说 “dianping” 这个值不存在。而当我们需要查询 “baidu” 这个值是否存在的话,那么哈希函数必然会返回 1、4、7,然后我们检查发现这三个 bit 位上的值均为 1,那么我们可以说 “baidu” 存在了么?答案是不可以,只能是 “baidu” 这个值可能存在。

这是为什么呢?答案跟简单,因为随着增加的值越来越多,被置为 1 的 bit 位也会越来越多,这样某个值 “taobao” 即使没有被存储过,但是万一哈希函数返回的三个 bit 位都被其他值置位了 1 ,那么程序还是会判断 “taobao” 这个值存在。

支持删除么

目前我们知道布隆过滤器可以支持 add 和 isExist 操作,那么 delete 操作可以么,答案是不可以,例如上图中的 bit 位 4 被两个值共同覆盖的话,一旦你删除其中一个值例如 “tencent” 而将其置位 0,那么下次判断另一个值例如 “baidu” 是否存在的话,会直接返回 false,而实际上你并没有删除它。

如何解决这个问题,答案是计数删除。但是计数删除需要存储一个数值,而不是原先的 bit 位,会增大占用的内存大小。这样的话,增加一个值就是将对应索引槽上存储的值加一,删除则是减一,判断是否存在则是看值是否大于0。

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

很显然,过小的布隆过滤器很快所有的 bit 位均为 1,那么查询任何值都会返回“可能存在”,起不到过滤的目的了。布隆过滤器的长度会直接影响误报率,布隆过滤器越长其误报率越小。

另外,哈希函数的个数也需要权衡,个数越多则布隆过滤器 bit 位置位 1 的速度越快,且布隆过滤器的效率越低;但是如果太少的话,那我们的误报率会变高。

image

k 为哈希函数个数,m 为布隆过滤器长度,n 为插入的元素个数,p 为误报率。

至于如何推导这个公式,我在知乎发布的文章有涉及,感兴趣可以看看,不感兴趣的话记住上面这个公式就行了。

最佳实践

常见的适用常见有,利用布隆过滤器减少磁盘 IO 或者网络请求,因为一旦一个值必定不存在的话,我们可以不用进行后续昂贵的查询请求。

另外,既然你使用布隆过滤器来加速查找和判断是否存在,那么性能很低的哈希函数不是个好选择,推荐 MurmurHash、Fnv 这些。

大Value拆分

Redis 因其支持 setbit 和 getbit 操作,且纯内存性能高等特点,因此天然就可以作为布隆过滤器来使用。但是布隆过滤器的不当使用极易产生大 Value,增加 Redis 阻塞风险,因此生成环境中建议对体积庞大的布隆过滤器进行拆分。

拆分的形式方法多种多样,但是本质是不要将 Hash(Key) 之后的请求分散在多个节点的多个小 bitmap 上,而是应该拆分成多个小 bitmap 之后,对一个 Key 的所有哈希函数都落在这一个小 bitmap 上。

参考资料

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/329417.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Oracle入门(十四)之PL/SQL

一、PL/SQL 基本语法 PL/SQL语言是模块式的过程化SQL,是oracle公司对SQL的扩展。 (1)(2)(3)(5)(6)(7)数据类型Number 数字型Varchar2 …

26.文件使用磁盘的代码实现

【README】 1.本文内容总结自 B站 《操作系统-哈工大李治军老师》,内容非常棒,墙裂推荐; 2.文件内容复习: 1)如何从生磁盘抽象为文件? 核心是从字符流位置算出盘块号;2)如何算出盘…

.NET Core全新的配置管理[共9篇]

提到“配置”二字,我想绝大部分.NET开发人员脑海中会立马浮现出两个特殊文件的身影,那就是我们再熟悉不过的app.config和web.config,多年以来我们已经习惯了将结构化的配置信息定义在这两个文件之中。到了.NET Core的时候,很多我们…

redis存opc_KEPServerEX6完整免费版

KEPServerEX6完整免费版是一款先进的连接平台,主要用于为您的应用程序提供单一来源的工业自动化数据,通过连接、管理、监视和控制不通的自动化设备和应用程序来实现工业数据。具有严谨的技术特征,支持多达250种以上的通讯协定,可连…

Oracle入门(十四B)之PL/SQL异常处理

定义:程序执行过程的警告或错误成为例外(Exception) 一、常见预定义错误 二、非预定义错误及用户定义错误 (1)非预定义oracle错误其他标准的oracle错误,可以自定义异常名,将其与指定oracle错误关联,由系统触发。 例子…

C#读书雷达 | TW洞见

大家都知道,ThoughtWorks的技术雷达每年都会发布两到三次,它不但是业界技术趋势的标杆,更提供了一种卓有成效的方法论,即打造自己的技术雷达。在这种思想的驱动下,我们诞生了自己的读书雷达。但这份雷达略显high level…

27.目录与文件系统

【README】 1.本文内容总结自 B站 《操作系统-哈工大李治军老师》,内容非常棒,墙裂推荐; 2.第4层抽象:抽象整个磁盘到文件系统 【1】文件系统,抽象整个磁盘(第4层抽象) 【图解】整个磁盘抽象1…

dd命令打包多个文件_linux的tar命令详情;linux多个文件压缩打包到一个压缩文件...

tar命令可以用来压缩打包单文件、多个文件、单个目录、多个目录。Linux打包命令_tartar命令可以用来压缩打包单文件、多个文件、单个目录、多个目录。常用格式:单个文件压缩打包 tar czvf my.tar.gz file1多个文件压缩打包 tar czvf my.tar.gz file1 file2,...(file…

28.文件目录解析代码实现

【README】 1.本文内容总结自 B站 《操作系统-哈工大李治军老师》,内容非常棒,墙裂推荐; 背景: 磁盘格式化后,其组成部分包括引导块,超级块,inode使用位图,盘块使用位图&#xff0…

Oracle入门(十四A)之PL/SQL 基本结构

一、条件控制语句 &#xff08;1&#xff09;条件语句Iif…then…end if形式1:if <布尔表达式> then…(pl/sql和sql)…end if;&#xff08;2&#xff09;条件语句II if…then…else … end if 形式2&#xff1a;if <布尔表达式> then…(pl/sql和sql)else…end if;…

利用记事本创建一个ASP.NET Core RC2 MVC应用

步骤一、安装最新的.NET Core SDK 我们可以根据自身的操作系统环境从https://github.com/dotnet/cli上下载.NET Core最新的SDK&#xff0c;这个SDK包含.NET Core Runtime和一些有用工具&#xff08;比如命令行&#xff09;。如果你已经安装了老旧的版本&#xff0c;我个人建议你…

datatable中某一列最小值_获取DataTable 某一列所有值

//获取某一列值string orderids (from d in dt.AsEnumerable() select d.Field("OrderID")).ToList().ListToString();/// /// 判断字符串是否在某字符串数组当中/// /// /// /// public static bool In(this string value, params string[] items){return items.An…

29.操作系统对磁盘的4层抽象小结

【README】 本文总结了操作系统 对磁盘的4层抽象&#xff0c;并给出了详细介绍的post 链接&#xff1b; 【1】对磁盘的4层抽象 【1.1】对磁盘的第1层抽象 通过盘块号读写磁盘&#xff08;读写多个扇区&#xff09;&#xff1b; 因为磁盘底层操作的单位是扇区&#xff08;51…

Oracle入门(十四C)之转换函数

一、数据转换类型 为数据库创建表时&#xff0c;SQL 程序员必须定义在表的各个字段中存储何种数据。在 SQL 中&#xff0c;有几种不同的数据类型。这些数据类型用于定义每个列中可以包含的值的范围。 &#xff08;1&#xff09;在本文中将使用以下数据类型VARCHAR2 CHAR NUMBER…

发布在即!.NET Core 1.0 RC2已准备就绪

先说点废话&#xff0c;从去年夏天就开始关注学习ASP.NET Core&#xff0c;那时候的版本还是beta5&#xff0c;断断续续不停踩坑、一路研究到11月份RC1发布。 在这个乐此不疲的过程里&#xff0c;学习了很多新的东西&#xff0c;对ASP.NET Core也是越来越喜爱。然而到现在&…

1.java IO模型(BIO,NIO,AIO)

【README】 本文介绍了 3种 java io模型&#xff0c;包括 BIO&#xff0c;NIO&#xff0c; AIO&#xff1b; IO模型名称 描述 工作原理 BIO-Blocking IO 同步并阻塞式IO 一个服务器线程处理一个客户端连接 NIO-Non-blocking IO 同步非阻塞式IO 一个服务器线程处理多个…

Oracle入门(十四D)之常规函数

一、NULL处理 &#xff08;1&#xff09;函数的计算过程 到目前为止&#xff0c;您已经学会了在简单语句中应用单行函数。不过&#xff0c;函数可以嵌套任意层。所以&#xff0c;了解嵌套函数的计算过程非常重要。下例就是一个嵌套函数。其计算过程是从最里层开始计算&#xff…

python定义函数prime判断是否是素数_用自定义函数判断素数 用C语言编写自定义函数prime(int x),判断x是否为素数?...

用C语言编写自定义函数prime(int x)&#xff0c;判断x是否为素数&#xff1f;int prime(int x){int i&#xff0c;kk(int)sqrt( (double)x )for(i2i&ltki )if(x%i0)break// 如果完成所有循环&#xff0c;那么x为素数if(i&gtk)retrun 1elsereturn 0}C语言&#xff0c;编…

构建高性能.NET应用之配置高可用IIS服务器-第一篇:IIS必须掌握的知识

正确而合理的配置IIS是构建一个高性能和高可扩展应用的基础。虽然很多的时候采用默认的配置就已经可以处理一般的情况&#xff0c;但是随着站点应用的发展&#xff0c;特别是当访问量稍微大一点的时候&#xff0c;就会暴露出很多我们认为的“奇奇怪怪”的问题。 所以&#xff0…

3.NIO选择器(基于NIO的服务器与客户端通讯)

【README】 本文总结自B站《尚硅谷netty》&#xff0c;很不错&#xff1b; 【1】选择器Selector&#xff08;多路复用器&#xff09; 【1.1】基本介绍 1&#xff09;Java 的 NIO&#xff0c;用非阻塞的 IO 方式。可以用一个线程&#xff0c;处理多个客户端连接&#xff0c;就…