在计算机科学中,我们常常会碰到时间换空间或者空间换时间的情况,即为了达到某一个方面的最优而牺牲另一个方面。
Bloom Filter在时间空间这两个因素之外又引入了另一个因素:错误率。在使用Bloom Filter判断一个元素是否属于某个集合时,会有一定的错误率。也就是说,有可能把不属于这个集合的元素误认为属于这个集合(False Positive),但不会把属于这个集合的元素误认为不属于这个集合(False Negative)。在增加了错误率这个因素之后,Bloom Filter通过允许少量的错误来节省大量的存储空间。
什么是Bloom Filter
Bloom Filter是一种空间效率很高的随机数据结构,
它的原理是,当一个元素被加入集合时,通过K个Hash函数将这个元素映射成一个位阵列(Bit array)中的K个点,把它们置为1。检索时,我们只要看看这些点是不是都是1就(大约)知道集合中有没有它了:如果这些点有任何一个0,则被检索元素一定不在;如果都是1,则被检索元素很可能在。
在判断一个元素是否属于某个集合时,有可能会把不属于这个集合的元素误认为属于这个集合(false positive)。因此,Bloom Filter不适合那些“零错误”的应用场合。而在能容忍低错误率的应用场合下,Bloom Filter通过极少的错误换取了存储空间的极大节省。
Bloom Filter示例图
image.png在这个示例中, 我们的Bloom Filter由一个30 bits的Bit Vector以及3个Hash Functions来构成。 我们将三个元素S1, S2和S3分别插入这个Bloom Filter中。 然后对另外三个新元素S1, Sx和Sy进行查询。 由图所示, S1和Sx将被认为属于这个Bloom Filter, 因为所以相应的bit位均为1, 而Sy则被视为不属于这个Bloom Filter。
但是, 其中Sx为一个false positive的答案, 因为在插入的时候我们并没有插入这个元素。False Positive的答案是由Hash Collision造成的。我们可以根据要插入的元素的个数来变化BF的长度,从而减少误判率。
Bloom Filter参数
Bloom Filter 参数主要有四个:
-
N : 需要插入Bloom Filter的最多的元素的个数
-
M : Bloom Filter中bit位的个数
-
K : Hash Functions的个数
-
P : Bloom Filter的False Positive rate
简单的概括为:
用K个Hash Functions, 将N个元素插入到一个M bits的Bloom Filter中, 使这个Bloom Filter的任意元素的误判概率将不会大于P。
N : 是我们预估的要存储的数量
P: 是我们期望的误判率
因此我们要根据这两个已知参数来推到出Bloom Filter中bit位的个数M和hash函数的个数K。
Hash函数的选择
哈希函数的选择对性能的影响应该是很大的,一个好的哈希函数要能近似等概率的将字符串映射到各个Bit。选择k个不同的哈希函数比较麻烦,一种简单的方法是选择一个哈希函数,然后选择k个不同的参数。
Guava的实现是对元素通过MurmurHash3计算hash值,将得到的hash值取高8个字节以及低8个字节进行计算,得到当前元素在bit数组中对应的多个位置。
image.pngBloom Filter应用场景
常见的几个应用场景:
- 在推荐系统中,将已推荐的的用户存入bloom filter中。
- 爬虫过滤已抓到的url就不再抓,可用bloom filter过滤。
- 垃圾邮件过滤。如果用哈希表,每存储一亿个 email地址,就需要 1.6GB的内存。而Bloom Filter只需要哈希表 1/8到 1/4 的大小就能解决同样的问题。
网友评论