赞
踩
布隆过滤器用于快速检测不存在数据,主要用位数组的结构来存储。其中为了保证布隆过滤器有适当的正确率通常会设置几个参数。
设:
k = hash函数个数,用于将一个数据通过不同hash函数计算为不同值,如“test” hash1-> 10,hash2-> 91, hash3->88等等,其中hash值即为位数组下标。如上面计算的三个值则位数组上坐标为10、91、88的位置上会被标记为1,其他位置还是0。
n = 数据量大小。如:现有一个100万文件的文件夹,我手中有一个文件不知道这个文件夹中是否有这个文件,如果没有就放进去,有的话我再另外处理。此时n则是100万
m = 位数组长度。如上面经过hash计算的值是小于一个最大值的,这个最大值则是这个位数组的长度。
p = 布隆过滤器正确率。hash计算的值位数是有限的,当数据量大了之后必然存在多个值重复交叉的问题,例如有另外两个数据三个hash函数算出的值分别是(11,10,88),(91,54,10),那如果这时再检测并没有存入的“test”它的hash值为(10,91,88)在位数组中是存在的。这时就会误报“test”已存在。那么这个误报率就是p。这里也可以看出布隆过滤器并不适合检测数据一定存在,而适合检测数据一定不存在。
使用布隆过滤器我们自然想要误报率p不能太高,当然长度m也不能太大不然还不如直接用其他更准确的数据结构。
那么这些参数的关系是怎样的呢。这里直接给出公式:
显然k值我们只能取整数,那么对应的p值为多少呢,这里我给出几个常见值对应表,
其中k/ln2用系数r表示即
k | p | r |
1 | 0.5 | 1.442695041 |
2 | 0.25 | 2.885390082 |
3 | 0.125 | 4.328085123 |
4 | 0.0625 | 5.770780164 |
5 | 0.03125 | 7.213475204 |
6 | 0.015625 | 8.656170245 |
7 | 0.0078125 | 10.09886529 |
8 | 0.00390625 | 11.54156033 |
9 | 0.001953125 | 12.98425537 |
10 | 0.000976563 | 14.42695041 |
我们可以看到当k取5时的误判率已经小于5%,此时的系数约等于7。也就是说,如果数据量为100万,那么位数组长度需要700万才能保证使用5个hash函数时误判率小于5%。700万位,约等于875kb。如果一个文件只有1k大小,总大小也将近1G了。通过布隆过滤器,只需要875k的内存大小便能快速判断某个文件是否在这个文件夹中,且准确率高达96.8%。
布隆过滤器在大量数据判断是否存在的场景非常有用,速度快,占用内存少。
当然布隆过滤器最耗时可能在hash函数中。此时选择的hash函数也要考虑使用性能较高的hash函数才能使整体效率较高。当然hash函数的散列均匀度也影响误判概率。此文中的公式是默认所有hash函数计算的值是绝对均匀的。
说了这么多废话,你肯定会问:能不能给力点啊老师!talk is cheap,show me the code.
好了,google.guava已经给你实现好了。BloomFilter,用静态方法create(int parm1,double param2)进行构建。第一个参数是你准备填充的数据总量,即文中的n。第二个参数是失败率,如你期望失败率为5%,则参数传0.05;当然,这是在java语境中的对象过滤。所以,理论上你把失败率设置为很低也不会太占用内存,比如0.00000000001。当然前提是你的总量不会太大。不过,第一个参数也限定了是个int而不是long。虽然组合起来可能会让布隆过滤器占用内存很大。但,一般的应用,你的失败率只要不设置的过分离谱,谁在乎呢。
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。