一文搞定布隆过滤器

写在前面,本文参考了guide哥的 bloom-filter 以及左神在牛客上的 算法入门课程。由于布隆过滤器在现在实在是太常用了,因此这个知识在面试中经常问到,最后我会查阅并且总结一下常见的面试题目以及相应的思路。

布隆过滤器的组成

bloom提出的布隆过滤器,由两部分组成——哈希函数以及位数组,其中位数组如下所示:

在这里插入图片描述
位数组中的每个元素都只占用 1 bit ,并且每个元素只能是 0 或者 1。这样申请一个 100w 个元素的位数组只占用 1000000Bit / 8 = 125000 Byte = 125000/1024 kb ≈ 122kb 的空间。

比特类型的数组,不同于int long类型的数组。但是在实现的时候,可以用int类型的数组来拼凑,也就是说一个32个bit的int类型的数字,实际上是占用了32个bit。

原理介绍

  • 当一个元素加入布隆过滤器中,会有如下操作:
  1. 使用哈希函数对要插入的元素值进行计算,得到哈希值(有可能有多个哈希函数
  2. 根据哈希值,在位数组中把对应下标的值设置为1
  • 判断一个元素是否存在于布隆过滤器中,有如下操作:
  1. 给定元素哈希计算
  2. 得到值之后判断数组中每个元素是否都为1,如果是,那么这个值在布隆过滤器中,如果有一个值不为1,说明不在

如上所说,布隆过滤器可以判断极大容量的样本中是否存在某个值,并且对空间特别友好;相比之下,如果是哈希hashmap,那占用的内存空间将是极大的浪费,100亿个URL,每个URL64字节,需要用到640GB的内存。

注意: 布隆过滤器会多报,但是绝对不会导致漏报。

首先准备多个哈希函数,对于任何一个给定的字符串,都用哈希函数计算一遍得到一个哈希值hash,然后再准备一个长度是m的位数组 array,令 array [hash%m] = 1 (初始化的时候array等于全0)。然后对于所有要进行判定的URL重复上述这个过程,所有的URL字符串判定结束,布隆过滤器的构建阶段就完成了。


对于 k 个哈希函数以及位数组长度是等于m的布隆过滤器来说:

  1. 如果m比较小,那么失误率肯定是非常大的,因为只需要几个值就能把所有的位置给描黑。如果m特别大,能达到很好的准确率,因为构建整个布隆过滤器之后得到的位数组的1值是相当稀疏的,此时多报率就会比较客观,但是于此同时,如果m特别大,那需要花费的内存空间就上升。
    因此存在一个合理的m值使得所需内存容量可以接受并且失误率也是满足系统要求的。
  2. 如果 k 比较少,那么采纳到的字符串的特征就比较少,此时错误率也会上升。如果k比较大,字符串的特征是充分采集到了,但是对于长度为m 的位数组来说,就很容易达到一个饱和的 1 值填充状态,同样可能导致错误率上升。
    因此存在一个合理的k ,使得k个哈希函数的情况下,布隆过滤器的过滤效果最佳。

应用

  1. 判断给定数据是否存在:比如判断一个数字是否在于包含大量数字的数字集中(数字集很大,5亿以上!)、 防止缓存穿透(判断请求的数据是否有效避免直接绕过缓存请求数据库)等等、邮箱的垃圾邮件过滤、黑名单功能等等。
  2. 去重:比如爬给定网址的时候对已经爬取过的 URL 去重。

面试题总结

  • 有一个100亿个字符串的文件,是一个黑名单,给定一个URL,判定是否在这个文件中?
    answer:
    将这个100亿个字符串的文件读入到一个布隆过滤器中,将URL哈希之后得到哈希值从位图中判定是否存在在布隆过滤器中。

  • 由于web世界是互相连通的世界,由一个网页可能跳转到另外一个网页,因此给定一个网络爬虫任务,共有一万条URL,要求对这些网页以及子网页和网页中能跳转的网页进行通用爬虫,并且要降低重复爬取的可能性。
    answer:
    每次爬一条URL,就判断URL是否存在于布隆过滤器中,如果没有,就加入到位图数组中,并且进行爬取;如果有,就跳过爬取。

  • hadoop 分布式文件系统
    hadoop的特点就是分布式,而且是分支特别多的分布式,对于其中一个文件,hadoop并不是直接遍历这个文件的key值是否存在于每个文件,这样的代价太高了,对于每个分文件系统,都维护着一个布隆过滤器。由于对于单个的key值来说,每个布隆过滤器只需要计算一次,所以即使有多个文件系统可能疑似存在这个key值,代价也不是很高,只需要在每个分文件系统下再依次遍历即可。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值