一个文件有100亿个字符串(不重复),每个字符串为64个字节,现在要实现一个黑名单系统,该文件所有字符串加载到该黑名单中,当输入一个字符串时,系统需给出该字符串是否在黑名单上。
(类似应用场景:爬虫去重,比如开一定数量的爬虫,需要爬虫爬取不同的内容,即每个爬虫爬之前都要去名单上查询该地址是否爬过,没爬过就爬取并将其记录到名单上。)
分析:
(1)若单纯用哈希表,那么100*64 = 6400亿,即640G的内存,爆炸。
·布隆过滤器:
应用:应用于如上述样本量巨大的黑名单,即要在巨大样本量中查找目标是否在名单上。
特征:
(1)好处省空间(2)坏处是会有一定的失误率,这个失误率在于,只要样本在名单上就一定能检测,但样本不在名单上也可能判断到在名单上。
实现:
利用位图,如一个4字节的空间,即有32位,那么位图长度就是32。
大致过程就是利用一定数量k的哈希函数,在模上m(即位图长度),得到的数就是位图中的下标,就在该下标中把该位改为1(涂黑)。
把所有样本都这样处理完。
那么查询时,就把要查询的字符串经过k个哈希函数,再模上m,再到位图上相应位置查询改位是否为1。只要k个数查到都是1,那么这个字符串就肯定在黑名单中。那么失误率在于,要是m较小或怎样的,样本中的字符串把很多地方都涂黑了,那么在查询一个字符串时,即使该串不在黑名单中,也可能将其判断为在名单中。
Q:那么怎么确定k和m的值?
m为位图长度,与单样本字节数无关,只要样本能通过哈希函数转换为一个数值就行了。
以下是失误率p和m,k之间的关系图。(n样本数)
以下是m,k和实际失误率的计算公式(数学推导省略)m,k向上取整。
Q:哈希函数怎么设计?
比如有两个哈希函数原型,得到a,b两个值,那么a+ib的值就可以看成是经过第i个哈希函数得到的值,即f1(n) + if2(n)。
·hadoop布隆过滤器模型
比如一个分布式文件,要找到key属于哪个文件,那么为每个文件装设一个布隆过滤器,把key值经哈希函数再模上后与每个文件的布隆过滤器比较,因为存在失误率,所以可能查询到有几个文件含有这个key,那么范围就缩小了,可以利用遍历方式查找,或者再利用布隆过滤器查一次。