布隆过滤器(bloom filter)及php和redis实现布隆过滤器(2)

布隆过滤器处理流程

布隆过滤器应用很广泛,比如垃圾邮件过滤,爬虫的url过滤,防止缓存击穿等等。下面就来说说布隆过滤器的一个完整流程,相信读者看到这里应该能明白布隆过滤器是怎样工作的。

第一步:开辟空间

开辟一个长度为m的位数组(或者称二进制向量),这个不同的语言有不同的实现方式,甚至你可以用文件来实现。

第二步:寻找hash函数

获取几个hash函数,前辈们已经发明了很多运行良好的hash函数,比如BKDRHash,JSHash,RSHash等等。这些hash函数我们直接获取就可以了。

第三步:写入数据

将所需要判断的内容经过这些hash函数计算,得到几个值,比如用3个hash函数,得到值分别是1000,2000,3000。之后设置m位数组的第1000,2000,3000位的值位二进制1。

第四步:判断

接下来就可以判断一个新的内容是不是在我们的集合中。判断的流程和写入的流程是一致的。

误判问题

布隆过滤器虽然很高效(写入和判断都是O(1),所需要的存储空间极小),但是缺点也非常明显,那就是会误判。当集合中的元素越来越多,二进制序列中的1的个数越来越多的时候,判断一个字符串是否在集合中就很容易误判,原本不在集合里面的字符串会被判断在集合里面。

数学推导

布隆过滤器原理十分简单,但是hash函数个数怎么去判断,误判率有多少?

假设二进制序列有m位,那么经过当一个字符串hash到某一位的概率为:

1m

也就是说当前位被反转为1的概率:

p(1)=1m

那么这一位没有被反转的概率为:

p(0)=1−1m

假设我们存入n各元素,使用k个hash函数,此时没有被翻转的概率为:

p(0)=(1−1m)nk

那什么情况下我们会误判呢,就是原本不应该被翻转的位,结果翻转了,也就是

p(误判)=1−(1−1m)nk

由于只有k个hash函数同时误判了,整体才会被误判,最后误判的概率为

p(误判)=(1−(1−1m)nk)k

要使得误判率最低,那么我们需要求误判与m、n、k之间的关系,现在假设m和n固定,我们计算一下k。可以首先看看这个式子:

(1−1m)nk

由于我们的m很大,通常情况下我们会用2^32来作为m的值。上面的式子中含有一个重要极限

limx→∞(1+1x)x=e

因此误判率的式子可以写成

 p(误判)=(1−(e)−nk/m)k

接下来令t=−n/m,两边同时取对数,求导,得到:

p′1p=ln(1−etk)+klnet(−etk)1−etk

让p′=0,则等式后面的为0,最后整理出来的结果是

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/1956.html