深度解析布谷鸟过滤器(上篇)

news2024/10/5 3:18:38

深度解析布谷鸟过滤器

0 引言

布隆过滤器(Bloom Filter),诞生于UNIX元年(1970年)的一个老牛逼的过滤器,与时间戳同寿,经久不衰老而弥坚,查重性能至今令人非常满意。美中不足的是有一点误判率并且支持删除元素比较困难。44年后,卡内基梅隆大学的Bin Fan等人发了篇文章,标题是《布谷鸟过滤器:雀食吊过布隆》,号称有更好的空间利用率、更高的性能、更低的误判率、对删除操作更好的支持。听起来有点东西,深入文章研究下。

1 相关研究(又名:全靠同行承托)

1.1 布隆过滤器和它的各路变种

1.1.1 标准布隆过滤器

标准布隆过滤器仅支持插入查找两个操作,并且存在一个假阳率ε,如果希望假阳率更低,那么就需要付出更高的空间代价。

通俗的翻译一下假阳率,这个概念后文可能还会出现。我向布隆过滤器查询,a是否存在,如果返回不存在,那就100%不存在,不接受反驳。如果返回存在,那就要小心了,因为它有ε的概率是错的,实际上a并不存在。当然,我实际工作中使用一般会让ε0.000001这样很小很小,1亿次错个1百1千次之类的,可以接受。

布隆过滤器的工作原理非常简单,k个随机哈希函数和1个长长的bit数组(初始为全0),插入一个元素时,使用k个哈希函数进行计算,并根据计算结果把bit数组中对应的k个比特位置为1。查询的时候也是同理,进行相应的计算后,查询对应的k个位置是不是都为1,如果都是1,那么说明已存在,否则说明不存在。想必读到这里,已经能领悟到假阳率出现的根源了吧。

在实际生产环境中,我们首先选取一个ε值,例如我用的是0.000001,即百万分之一,与之对应的哈希函数个数k的选取,则需要一点小小的计算:

log ⁡ 2 1 ε \log_2 \frac1 ε log2ε1

通过一系列的概率极限偏微分方程的计算可以得到这个值,是空间最优的一个解,这里就不做推导了。根据我的ε值可以计算得到,k=20,即我们需要设置20个哈希函数。在最优解下,每个元素需要的存储空间为:

1 ln ⁡ 2 ∗ log ⁡ 2 1 ε \frac1 {\ln2}*\log_2 \frac1 ε ln21log2ε1
(注:原论文中采用的系数1.44为近似值,实际公示推导结果为 1 ln ⁡ 2 \frac 1 {\ln2} ln21)



则如果需要对n个元素做查重需要的空间如下:

n ∗ 1 ln ⁡ 2 ∗ log ⁡ 2 1 ε n*\frac1 {\ln2}*\log_2 \frac1 ε nln21log2ε1

显然,单个元素的存储空间只与ε有关,而与元素本身的大小并无关系。根据信息论原理单个元素需要的最小空间为 log ⁡ 2 1 ε \log_2 \frac1 ε log2ε1,布隆过滤器需要的空间仅比信息论最小值高约44%,这样的空间利用率,不可谓不高效。

标准布隆过滤器优点突出,缺点也非常显著,那就是它不支持删除操作。为了解决这一点,有人提出了一种布隆过滤器的扩展,Counting Bloom filters ,我也不知道怎么翻译,就叫计数布隆过滤器吧。

1.1.2 计数布隆过滤器(CBF)

首先思考下为什么标准布隆过滤器不支持删除操作,插入操作是把对应的k位bit置为1,那删除的时候我置为0不就行了?显然是不行的,万一元素B有某一位bit[x]和元素A重复了,那在删除A的过程中,bit[x]就置为0了,那么我再去查找B,就会发现bit[x]=0,B不存在,那就完犊子了,因为我们并没有删除过B。

要解决这一问题也非常简单,无非是因为一个bit位能包含的信息太少了,这个问题加钱就能解决。把每个bit位改成一个计数器,本来bit[x]只能0 ⇒ \rArr 1,现在有了计数器,就可以bit[x]+1了,删除的时候bit[x]-1。对于上述A, B元素,bit[x]=2,删除A元素bit[x]=1了,丝毫不会影响到B元素后续的查找。

关于计数器的位数的计算,有点高深,有一步什么斯特林公式的变换完全没看懂,反正4位就很够用了。1个bit位需要对应成一个4位的计数器,所以CBF的空间开销差不多是标准布隆的4倍。

这种计数器的方法可以说是简单粗暴,在空间的使用上也有些奢侈了,显然还有进一步的优化空间。

1.1.3 Blocked Bloom filters

来自卡尔斯鲁厄大学的FELIX PUTZE等人在2007年的研究《Cache-, Hash- and Space-Efficient Bloom Filters》,这个我也没找到啥中文资料,冒昧翻译为分块布隆过滤器,这是标准布隆过滤器的又一变种,它提升的方向是进一步的提高性能。布隆过滤器本身性能已经非常优越了,但仍有某些场景对性能有更极致的追求,例如阿里云对RuntimeFilter进行性能优化的时候就把标准布隆过滤器替换成了Blocked Bloom filters。

性能提升付出的代价是更高的假阳率,多用了一点空间,同时它依然不支持删除操作。

这个变种并不符合我的工作需要,所以没有进行更深入的学习研究,1.1.2提到了CBF对空间的浪费,下面来看下如何对其进行优化提升。

1.1.4 d-left Counting Bloom filters

翻译这活真不是人干的,我绞尽脑汁给它起了个名字:基于多子表均衡左优先存储哈希表的计数布隆过滤器。

要理解这个变种,首先要理解d-left hashing,我自认为翻译的还是到位的,多子表均衡(d)左优先存储(left)哈希表(hashing)。把整个哈希表分成d个从左到右连着的子表,每个子表对应一个不同的哈希函数,当加入一个新元素时,分别计算d个哈希函数,得到d个不同的位置,然后将新元素加入到负载最轻的位置,如果有多个子表负载相同且均为最轻,则默认加入到最左边的子表。同理,进行查找操作时自然也就需要分别进行d次计算和查找。

虽然这种过滤器的名字里依旧包含Counting,但这只是表示它是CBF的变种,实际它已经抛弃了计数器,转而为每个元素存储了一个指纹,而这个指纹,正是使用了d-left hashing进行存储的。需要进行删除操作时,直接从d-left hashing中移除对应的指纹即可。

通过d-left hashing存储指纹的方式,d-left CBF可以比CBF节省约50%的存储空间,亦即标准布隆过滤器的1.5~2倍左右。

d-left CBF和本文将重点介绍的布谷鸟过滤器有很多相似之处,这里暂时按下不表,先看另一种非常流行的过滤器——Quotient filters

1.1.5 Quotient filters

商过滤器,中文资料也是乏善可陈,因此我辛苦一下,在这里做一个最通俗易懂的中文讲解。

据说商过滤器是诞生于《计算机程序设计艺术(第3卷)》6.4节的习题13,我特地去看了下原题,嗯,劳资题目都看不懂啊!我要有这么难的作业必不可能拿到毕业证书啊!

言归正传,商过滤器只进行一次哈希函数计算,显然比上述的k次d次计算来的效率要更高,另外商过滤器也支持删除操作。这两点就是他相较于标准布隆过滤器的主要优点,没错,标准布隆过滤器就是战斗力计算单位。

首先我们构造一个 3 ∗ 2 r 3*2^r 32rbit位长度的哈希表,给每3位bit对应分配一个槽,即有 2 r 2^r 2r个槽,构造好之后我们暂且把他放在一边,等会儿再说怎么用。

然后我们来对一个元素x进行以下3次运算:

① 对元素x进行一次哈希函数的运算,这里记为 f ( x ) f(x) f(x)
② 对 f ( x ) f(x) f(x)做一次除法运算,取其商 f q ( x ) = ⌊ f ( x ) / 2 r ⌋ f_q(x)=\lfloor f(x)/2^r\rfloor fq(x)=f(x)/2r
③ 对 f ( x ) f(x) f(x)做一次模运算,得到余数 f r ( x ) = f ( x ) m o d    f q ( x ) f_r(x)=f(x) \mod {f_q(x)} fr(x)=f(x)modfq(x)

假定8个元素,分别进行上述运算后,得到下面这样一组值,接下来我们把这组值填入到之前构造的哈希表中。

f f f f q f_q fq f r f_r fr
A1a
B1b
C3c
D3d
E3e
F4f
G6g
H6h

填入结果如下图所示
在这里插入图片描述
表格上方的0~9数字,用于表示每个槽的索引,根据商 f q f_q fq的值,将 f r f_r fr填入与 f q f_q fq对应的索引中。如第一个放入的A,商为1,则把a填入到索引为1的槽内,第二个放入B的时候,发现商也是1,而索引1的槽已经被A占用了,那就往后顺延一格,存入索引为2的槽内。C的商为3,则存入索引为3的槽内,DEFGH同理往后顺延。

前文我们说过,给每3位bit对应分配一个槽,槽存储了 f r f_r fr的值,3位bit则另有他用。这3位bit分别表示:

  • is_occupied: 是否被正确的占据了。重点不是这个槽有没有被占据,而是有没有被正确的占据,即有没有与槽位索引对应的商值。如A的商是1,那么槽位1就被正确的占据了。再看槽位6,G的商是6,而这个槽位已经被F占了,但槽位6仍然是拥有一个与它对应的商值的,虽然G不在槽位6,槽位6的is_occupied依然是1;
  • is_continuation: 是否连续的。以DE为例,他们的商值都是3,因为槽位3已经被C占据,他们被迫往后顺延,这种情况我们称DE对于C而言是连续,因此DE的is_continuation值均为1。而F的商值是6,和CDE就不再连续了,所以F这个槽位的is_continuation值为0;
  • is_shifted: 是否被移动了。主语是当前槽位内的值。如B,根据商值它应该放在槽位1,但被迫往后顺延到了槽位2,因此它的is_shifted值为1。C则原本就在槽位3,is_shifted为0,DEFGH都是同理,被迫往后顺延了,因此is_shifted都是1;

1.2 对比总结

过滤器类型空间消耗查找开销删除支持
标准布隆过滤器1kno
分块布隆过滤器1x1no
计数布隆过滤器3x ~ 4xkyes
d-left CBF1.5x ~ 2xdyes
商过滤器1x ~ 1.2x ⩾ \geqslant 1yes
布谷鸟过滤器 ⩽ \leqslant 1x2yes

注:k和d在上文中都有提及,不再解释;1x表示比1多一点点,3x ~ 4x表示为1的3~4倍左右;

相关的一些过滤器变种在这里就介绍完了,关于布谷鸟过滤器的深入研究,将在下篇中继续。

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

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

相关文章

Windows任务计划程序Task Scheduler笔记

微软文档居然搜不到了 Windows任务计划程序已经存在许多年了,原来在微软的TechNet上有详细的操作介绍的,现在发现网站改版,原来的介绍居然搜索不到了,微软的平台上出现这种事情,也是比较吃惊了。 添加任务计划不难 …

ORB-SLAM2 ---- Tracking::Relocalization函数

目录 1.函数作用 2.步骤 3.code 4.函数解释 4.1 将当前帧的描述子转化为BoW向量 4.2 用词袋找到与当前帧相似的候选关键帧 4.3 遍历所有的候选关键帧,通过词袋进行快速匹配,用匹配结果初始化PnP Solver 4.4 通过一系列操作,直到找到…

项目成本管理软件能为你做什么?

成本管理与企业在当前以及未来项目中取得成功的能力密切相关。投资可靠的项目成本管理软件可以带来巨大的节约。一个好的成本管理解决方案不会把它当作一个孤立的功能,而是把它作为项目和投资组合绩效的关键因素加以利用,并在各个项目之间进行数据关联。…

金山表单结果如何自动通知企业微信

金山表单内置了丰富的模版,从表单、接龙、问卷、投票,可以满足你各种表单数据数据收集的需求。但是很多用户经常也会有一个痛点,通过金山表单收集的信息,如何才能实时通知企业微信/钉钉/飞书呢? 比如防疫登记、安全复工…

1.2 异步相关概念:深入了解

1.同步(Synchronous) VS 异步(Asynchronous) 所谓同步,可以理解为每当系统执行完一段代码或者函数后,系统将一直等待该段代码或函数返回的值或消息,直到系统接收到返回的值或消息后才继续往下执行下一段代码或者函数,在等待返回值…

汽车行业大趋势——软件定义汽车

文章目录 前言一、软件定义汽车的驱动力二、SOA架构在软件定义汽车中的作用三、车载软件架构(内核、中间件、应用层)长期趋势总结前言 最早在2007年4月份的IEEE会议中提出“软件定义汽车”(SDV,Software Define Vehicle&#xff…

flask-admin菜鸟学习笔记

近期在工作中需要维护若干个信息表,在这个过程中需要经常对表格进行操作、交叉操作、各个表格同步,和某平台信息同步。。。在此过程中需要建立一个“隐性”的流程,要第一步同步A和B,再同步B和C,。。。而检索更是痛苦&a…

Python 中 4 个高效的技巧!

今天我想和大家分享 4 个省时的 Python 技巧,可以节省 10~20% 的 Python 执行时间。 反转列表 Python 中通常有两种反转列表的方法:切片或 reverse() 函数调用。这两种方法都可以反转列表,但需要注意的是内置函数 reverse() 会更改原始列表…

最近面了12个人,发现这个测试基础题都答不上来...

一般面试我都会问一两道很基础的题目,来考察候选人的“地基”是否扎实,有些是操作系统层面的,有些是 python语言方面的,还有些… 深耕IT行业多年,我们发现,对于一个程序员而言,能去到一线互联网…

托管海外服务器有哪些要求?

对于成长中的企业来说,需要使用自己的Web 服务器来有效地控制网站运营安全以及关键数据管理。但与此同时,创建一个高效的数据中心需要巨大的基础设施成本,24小时现场经验丰富的技术和管理支持团队来管理所有数据中心需求、服务器和数据等等。…

详细介绍NLP关键词提取算法

PageRank 算法 基于词图模型的关键词提取算法主要有 PageRank 和 TextRank。 PageRank 是 TextRank 算法的思想基础,TextRank 是 PageRank 在文本上的应用。 来源: Google 创始人拉里佩奇和谢尔盖布林于 1997 年构建早期的搜索系统原型时提出的链接分析…

uniCloud云开发及一键生成代码

uniapp云开发(云数据库) 准备工作 一、新建项目选择云开发 关联云函数 在cloudfouctions右键点击创建云函数 在base下的index.js中写入 use strict; exports.main async (event, context) > {//event为客户端上传的参数console.log(event : , ev…

PyG (PyTorch Geometric) 异质图神经网络HGNN

诸神缄默不语-个人CSDN博文目录 PyTorch Geometric (PyG) 包文档与官方代码示例学习笔记(持续更新ing…) 本文介绍使用PyG实现异质图神经网络(HGNN)的相关操作。 本文主要参考PyG文档异质图部分:Heterogeneous Graph…

Matplotlib可视化50图:气泡图(2)

导读 本文[1]将学习如何使用 Python 的 Matplotlib 库通过示例绘制气泡图。 简介 气泡图是散点图的改进版本。在散点图中,有两个维度 x 和 y。在气泡图中,存在三个维度 x、y 和 z。其中第三维 z 表示权重。这样,气泡图比二维散点图在视觉上提…

C语言 编译和链接

C语言 编译和链接引言翻译环境运行环境声明一、预定义符号二、#define 符号1. #define 定义标识符2. #define 定义宏宏带来的陷阱宏的两个特殊的使用场景① 使用 #,把一个宏参数变成对应的字符串② 使用 ##,将两个宏参数合并成一个符号宏参数的使用3. #d…

某度旋转验证码

案例地址:aHR0cHM6Ly96aXl1YW4uYmFpZHUuY29tL2xpbmtzdWJtaXQvdXJs 运行结果截图: 抓包分析, 整个流程如下 第一个包,提交参数是ak和时间戳(ak是定值) 返回的参数中,as和tk后面都会用到 点击提交,会弹出验证码,第二个包,请求参数的tk是第一个包返回的, ak同第一…

总算给女盆友讲明白了,如何使用stream流的filter()操作

一、引言 在上一篇文章中《这么简单,还不会使用java8 stream流的map()方法吗?》分享了使用stream的map()方法,不知道小伙伴还有印象吗,先来回顾下要点,map()方法是把一个流中的元素T转换为另外一个新流中的元素R&…

身边的那些信审人员都去哪了?

最近几天看到朋友圈很多信用卡审核中心的老同事(老同学)在秀到深圳9周年,在2013年的时候,大家都是一起通过校招来到了XX银行信用卡中心的信贷审批部,成为了信用卡人工审核员,那时候入职信贷审批部近百人&am…

这个算法不一般,控制拥塞有一手!

数字时代下,远程办公、线上协同成为刚需,直播带货等业务模式盛行,数据流量爆炸式增长,低时延、高流畅的网络传输诉求给数据中心的处理能力带来了极大挑战。RDMA作为一种新型网络传输技术,可大幅提升网络传输实效&#…

HTML期末学生大作业-节日网页作业html+css+javascript

🎉精彩专栏推荐 💭文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 💂 作者主页: 【主页——🚀获取更多优质源码】 🎓 web前端期末大作业: 【📚毕设项目精品实战案例 (10…