一. Bloom Fliter的应用场景:常见的URL黑名单过滤,假设黑名单中有100亿个URL,这时候如何以最小代价来存储这个url黑名单且能够判断一个URL是否在这个黑名单中(过滤),这时候如果允许有失误率,则就可以使用Bloom Fliter,否则还是乖乖使用HashMap结合分布式来处理。
二、 Bloom Fliter的局限:它有一定的误识别率:也就是有可能把一个本来不在这个Bloom Fliter(黑名单)中的数据给识别成在这个Bloom Fliter(黑名单)中,而一个在这个Bloom Fliter的数据它一定会返回true
三、Bloom Fliter的实现原理:Bloom Fliter本质就是一个bit数组(可以通过基本类型转化实现),每一位的值天然对应0,1可以用来表示true or false 然后其还内嵌了k个独立的hash 函数。
在构建或查找时:假设这个bit数组总共有m位。对于一个数据(比如url),我们先得出它的hashcode,然后Bloom Fliter中会内置k个独立的hash函数,此时再将这个url的hashcode代入这k个hash函数去计算出k个hash值,然后让这k个hash值 %m,得到一个hash slot,然后将bit数组的hash slot位置置1(涂黑)(查找时就查这k个hash slot,若这k个hash slot的值全为1(全被涂黑了)则表示其存在于这个Bloom Fliter中,只要有1个不为1那么就认为它不存在于这个Bloom Fliter中,为什么要使用多个hash函数呢,如果仅使用一个hash函数时,当发送hash冲突时不就很容易发生误识别)。但这里有可能出现一个问题:当bit数组不够大时,而此时的数据量又很大或者采用了较多的hash函数(k比较大),那么此时很又可能出现再经过若干次计算后,你的bit数组整个被置1,全被涂黑了,这样此时的再查其他数据时,一定恒return true(这也是为什么会出现误识别的情况,或者说Bloom Fliter无法避免有一定的误识别率)
四、Bloom Fliter的实现
1、如何借助基本类型数组来实现bit数组
int[] arr = new int[1000];//对应100032bit ,也就是这个arr能对应100032位
那么怎么计算呢?比如我想把第 30000个bit位置1,那么怎么做呢?
int intIdx = idx/32;//求出第30000个bit位对应arr的第几个位置上的数也就是对应是哪个arr[intIdx]
int bitIdx = idx%32;//求出第30000个bit位对应arr[intIdx]这个数的具体哪一bit位,联系二进制形式
arr[intIdx] = (arr[intIdx] | (1<<bitIdx)) ;
2、如何计算Bloom Fliter中要构建多大的bit数组
m = - (n*ln p)/ (ln 2)^2 其中 n为数据量的大小, P 为允许的误识别率
3、如何计算Bloom Fliter中需要多数个hash函数
k = ln2 * m/n
4、当m和k确定时如何确定此时的这个Bloom Fliter的误识别率