布隆过滤器

题目描述

比如,现在有100亿个url,这些url是黑名单,现在有一个搜索引擎公司,当你搜索这些url时,不予显示。
现在假设每一个url是64字节,也就是64B。现在有一个最基础的需求,判断一个url是否在这100亿中。
100亿个url,也没有顺序,不能二分查找,如果遍历的话,时间复杂度O(100亿)也太离谱了,因此只能用散列表实现,时间复杂度O(1)。

一般处理方式

将100亿数据放入散列表中,然后查找。先不说散列表中的其他结构所占空间,单单只是这100亿✖64B的数据,就得需要640G的内存,一台服务器是不太可能有640G内存的,而且这么大的内存来实现这个功能属实有点浪费资源。那么,用分布式处理,用散列函数分流,也能实现,假如一台机器64G内存,也需要10台。设想一下,有没有可能用一台电脑就能搞定这个呢?这就需要用到布隆过滤器了。

布隆过滤器

首先需要清楚,布隆过滤器是有失误率的。但是这个失误率,不是指的是存在于url集合中没有查找到的失误率,只要在,肯定能查找到的。而是,有可能某个url不在集合中,但是把这个url误判成黑名单的失误率。就好比,宁可错杀也不放过一个。在某些系统中,是可以允许这种失误的,就能使用布隆过滤器。如果系统不允许任何失误,就不能使用布隆过滤器。
布隆过滤器的本质,是一个比特类型的map。

布隆过滤器的过程
首先,怎么实现比特数组呢?
因为一个int类型是4字节,一个字节8比特,那么,一个int就是32个比特。

int[] arr = new int[1000];//其实这就是一个32000大小的比特数组

然后,100亿数据中,每来一个url,我们就用散列函数进行运算一下,将结果再与比特数组的长度取余,映射到比特数组上(比特数组的大小需要经过公式推理)。
补充:
<<是位移运算服, <<左移运算,>>右移运算,还有不带符号的位移运算 >>>.
左移的运算规则:按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零。
计算过程已1<<16为例,首先把1转为二进制数字 0000 0000 0000 0000 0000 0000 0000 0001
然后将上面的二进制数字向左移动16位后面补0得到 0000 0000 0000 0001 0000 0000 0000 0000
最后将得到的二进制数字转回对应类型的十进制

int index=30000;//假设对数组长度取余后的结果为30000
int intIndex=index/32;//这一步求出应该在第几块int中
int bitIndex=index%32;//这一步求出在那块int的第几位
arr[intIndex]=arr[intIndex] || (1<<bitIndex);//将二进制1左移16位后,将比特数组对应位变成1

上面运算完,我们就把一个url先经过散列函数后,又将其映射到比特数组上了,然后,我们将映射到的那一位比特从0变为了1。
这就是布隆过滤器了吗?可以是,也可以说不是。因为布隆过滤器往往需要K个散列函数。上面只是跑了一个散列函数后的结果,然后,依次把K个散列函数跑一遍,就是布隆过滤器的过程了。跑完后,相当于,一个url最终将比特数组上K个比特位从0变成了1。
这就是布隆过滤器的过程。当把所有url跑一遍后,布隆过滤器上的一部分比特是0,一部分是1。然后,当我们需要判断一个url是否满足时,依次计算那K个散列函数,然后映射到比特数组上,如果映射到的每一位都是1,说明满足,只要出现一位是0,就不满足。

上面就是布隆过滤器的全部过程,可以看出,最后检查时,是有可能出现一种情况:一个url映射后的所有比特对应的都是1,但是这个url并不在集合中,这就是布隆过滤器有失误率的原因。

布隆过滤器分析

原始散列表来实现
一个url占用64字节大小空间,散列表是需要将这个url挂在散列表中的,同时,散列表的索引,用int实现的话,也需要4个字节来保存int类型的索引。
布隆过滤器实现
对比普通散列表,布隆过滤器,首先,是不需要将url保存的,这个也是布隆过滤器最大的优化,只保存了url经过散列函数后再映射到比特数组后的比特位。其次,布隆过滤器也不需要占用一个int4字节来保存,最终只会占用K(K是散列函数的个数)个比特位。
普通散列表,记录了一个散列函数的散列结果以及原始的key(用链表或者红黑树挂在后面)。布隆过滤器,记录了key经过K个散列函数运算后的结果,不保存原始的key,并且用比特来记录散列后的结果,比int节省32倍空间。
总结一下,相当于,布隆过滤器的意思是,保存了K个不同散列函数的散列结果,如果再次跑相同url,还是这个结果,就证明是原来的url。就不需要像散列表那样将原始url用链表挂在后面了。

布隆过滤器公式

比特数组大小需要公式计算,设大小为m,样本数量为n=100亿,预期失误率为p=0.01%。
使用样本数量n和失误率p可以算出m,公式为:
在这里插入图片描述

求得 m = 19.19n,向上取整为 20n。所以2000亿bit,约为25G。这可比640G小太多了,完全一台服务器可以搞定。
所使用哈希函数个数k也需要用公式计算,可以由以下公式求得:
在这里插入图片描述
所以 k = 13.多,向上取整,即需要14个哈希函数。
因为m和k都是向上取整的,因此,最终的真实失误率,只可能比预期的低,不可能高,用下面公式可以计算出真实失误率:
在这里插入图片描述
通过 m = 20n, k = 14,可以通过以上公式算出设计的布隆过滤器的真实失误率为0.006%。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值