Bloom Filters by Example (链接:http://billmill.org/bloomfilter-tutorial/)
以下是关于布鲁姆过滤器的知识点
布隆过滤器是一种数据结构,快速和节省内存,能用于判定一个元素是否存在于一个集合中。
这种效率的代价是Bloom filter是一种概率数据结构,元素不是绝对的在组里或可能在组里。
Bloom filter的基本数据结构是一个位向量。
在以下文本,我们
用
ķ个
哈希值,m位的过滤器
,和n
个
已插入的元素来介绍Bloom filter
哈希函数
Bloom filter应使用的哈希函数是独立和均匀分布的,使哈希函数运行时尽可能的快。(而加密散列如sha1,尽管被广泛使用,但不是很好的选择)。
例子:简单的散列足够独立,其中包括 murmur, the fnv series of hashes, and Jenkins Hashes.
然而2016年8月31日的更新:Murmur(杂音)似乎被打破了。现在你可能更喜欢SipHash。
在一个快于加密哈希函数中可以看到区别,当开启一个 bloom filter 从md5到Murmur的实现时,增速提高到了~ 800%。
关于bloom filter的实现有个简短的调查
Cassandra uses Murmur hashes
Hadoop includes default implementations of Jenkins and Murmur hashes
python-bloomfilter uses cryptographic hashes
Plan9 uses a simple hash as proposed in Mitzenmacher 2005
Sdroege Bloom filter uses fnv1a (included just because I wanted to show one that uses fnv.)
Squid uses MD5
双散列
注意,您不需要选择两个或两个以上不同的哈希函数。相反,您可以通过两双散列函数创建任意数量的新散列函数。
给定两个独立的哈希函数a,b和一个value值 x,你可以创建一个新的哈希散列函数:
hashi(x, m) = (hasha(x) + i × hashb(x)) mod m
How big should Imake my Bloom filter?
能通过误报修改你
Bloom filter的过滤速度,这
是一个很好的特性。更大的过滤器将具有更少的误报,而较小的则误报会多一点。
误报率将约为(1-e-kn/m)k,所以你只需按你的期望插入n元素的数量,并尝试不同的k值和m值,为您的应用程序配置过滤器。
但这导致一个明显的问题:
How many hash functions should I use?
哈希函数越多,导致过滤器越慢,并且填满的更快。如果过少,可能会有很多误报。
当你必须选择ķ来创建过滤器,你必须确定n值大概在什么范围,一旦你确定了,你还要确定一个潜在的k(哈希函数的数量)和一个m(比特数)。
这似乎是一个困难的优化问题,但幸运的是,给定一个m和n,有一个函数能选择最优值k:(m/n)ln(2)
因此,要选择bloom filter的大小:
- 选择一个大概值n
- 选择一个值m
- 计算的最优值ķ
- 计算我们所选择的值的错误率n,m,和ķ。如果这是不可接受的,回到步骤2和改变m; 否则我们就完成了。
How fast and space efficient is a Bloom filter?
如何快速,节省空间
给定一个m比特和k个散列函数的bloom filter,复杂度是O(K)。
也就是说,每次想添加一个元素到集合,你只需要在ķ个散列函数中运行元素,将其添加到集合或检查所在的位。
空间优势很难总结,这取决于你愿意容忍的错误率。这也取决于元素插入的潜在范围;如果是非常有限的,使用一个确定的位向量会更好。如果你甚至不能大概的估计要插入的元素数量,你最好有一个哈希表或做一个可伸缩的bloom filter。
参考
1:布鲁姆过滤器的网络应用程序:调查,布罗德和Mitzenmacher。一个很好的概述。
2:维基百科,这对布鲁姆过滤器的出色和全面的网页
3:少散列,同样的性能,基尔希和Mitzenmacher
4:可扩展布鲁姆过滤器,阿尔梅达等人
5: 如何用c++撰写布鲁姆过滤器, Michael Schmatz
(如若有翻译或者知识错误,欢迎留言评论)