一文彻底搞定布隆过滤器

如果有一个网站有 100 亿 url 存在一个黑名单中,每条 url 平均 64 字节。这个黑名单要怎么存?若此时随便输入一个 url,你如何快速判断该 url 是否在这个黑名单中

不考虑细节的话,此题就是一个简单的查找问题。对于查找问题而言,使用散列表来处理往往(意味着并不是对于所有情况都适用)是一种效率比较高的方案。但是,对于这个题,如果使用散列表,那就悲剧了,你可以算算需要的内存空间-- 640G 的内存空间。又因为使用了散列表这种数据结构,而散列表是会出现散列冲突的,为了减少冲突,需要增加大量的冗余空间,最终内存空间可能需要超过 1TB。

位图(BitMap)

上面说过了散列表(hash)。这里说一些位图。如果有 1 千万个整数,分布在 1 到 1 亿之间,如何快速确定某个整数是否在这 1 千万个整数中呢?对于这种问题,我们可能会想到用1亿bit来构建一个结构,用位的0和1表示该位置的数字是否存在。如果第257个位置为1,则表示数字256在这1000万个数字中(数组下标从0开始)。

位图法:就是用每一位来存放某种状态,适用于大规模数据,但数据状态又不是很多的情况(数据分布相对均匀一些)。位图法有一个优势就是空间不随集合内元素个数的增加而增加。但它所需要的空间是和元素的最大值有关系的。如果数据分布非常不均匀,特别是数据量与最大值的比值非常小的时候,空间浪费会非常严重。

位图法的所占空间随集合内最大元素的增大而增大

缺点空间复杂度随集合内最大元素增大而线性增大

 

布隆过滤器

布隆过滤器(Bloom Filter)是对位图的一种改进,实际上是一个很长的二进制矢量和一系列随机映射函数。

可以用来判断一个元素是否在一个集合中。它的优势是只需要占用很小的内存空间以及有着高效的查询效率。

对于布隆过滤器而言,它的本质是一个位数组:位数组就是数组的每个元素都只占用 1 bit ,并且每个元素只能是 0 或者 1。

一开始,布隆过滤器的位数组所有位都初始化为 0。比如,数组长度为 m ,那么将长度为 m 个位数组的所有的位都初始化为 0。

0000000000
001m-2m-1

在数组中的每一位都是二进制位。

布隆过滤器除了一个位数组,还有 K 个哈希函数。当一个元素加入布隆过滤器中的时候,会进行如下操作:

  • 使用 K 个哈希函数对元素值进行 K 次计算,得到 K 个哈希值。
  • 根据得到的哈希值,在位数组中把对应下标的值置为 1。

 

图 1

 

 

举个例子,假设布隆过滤器有 3 个哈希函数:f1, f2, f3 和一个位数组 arr。现在要把 2333 插入布隆过滤器中:

  • 对值进行三次哈希计算,得到三个值 n1, n2, n3。
  • 把位数组中三个元素 arr[n1], arr[n2], arr[3] 都置为 1。

当要判断一个值是否在布隆过滤器中,对元素进行三次哈希计算,得到值之后判断位数组中的每个元素是否都为 1,如果值都为 1,那么说明这个值在布隆过滤器中,如果存在一个值不为 1,说明该元素不在布隆过滤器中。

 

布隆

很明显,数组的容量即使再大,也是有限的。那么随着元素的增加,插入的元素就会越多,位数组中被置为 1 的位置因此也越多,这就会造成一种情况:当一个不在布隆过滤器中的元素,经过同样规则的哈希计算之后,得到的值在位数组中查询,有可能这些位置因为之前其它元素的操作先被置为 1 了

如图 1 所示,假设某个元素通过映射对应下标为4,5,6这3个点。虽然这 3 个点都为 1 ,但是很明显这 3 个点是不同元素经过哈希得到的位置,因此这种情况说明这个元素虽然不在集合中,也可能对应的都是 1,这是误判率存在的原因。

所以,有可能一个不存在布隆过滤器中的会被误判成在布隆过滤器中。

这就是布隆过滤器的一个缺陷:存在误判。

但是,如果布隆过滤器判断某个元素不在布隆过滤器中,那么这个值就一定不在布隆过滤器中。总结就是:

  • 布隆过滤器说某个元素在,可能会被误判
  • 布隆过滤器说某个元素不在,那么一定不在

用英文说就是:False is always false. True is maybe true。

误判率

布隆过滤器可以插入元素,但不可以删除已有元素。其中的元素越多,false positive rate(误报率)越大,但是false negative (漏报)是不可能的。由于公众号内对于数学公式的排版不太友好,小吴就不在这贴出来了,具体的计算公式可以在网上查找到。

补救方法

布隆过滤器存在一定的误识别率。常见的补救办法是在建立白名单,存储那些可能被误判的元素。 比如你苦等的offer 可能被系统丢在邮件垃圾箱(白名单)了。

使用场景

布隆过滤器的最大的用处就是,能够迅速判断一个元素是否在一个集合中。因此它有如下三个使用场景:

  • 网页爬虫对 URL 的去重,避免爬取相同的 URL 地址
  • 进行垃圾邮件过滤:反垃圾邮件,从数十亿个垃圾邮件列表中判断某邮箱是否垃圾邮箱(同理,垃圾短信)
  • 有的黑客为了让服务宕机,他们会构建大量不存在于缓存中的 key 向服务器发起请求,在数据量足够大的情况下,频繁的数据库查询可能导致 DB 挂掉。布隆过滤器很好的解决了缓存击穿的问题。

参考:
https://juejin.im/post/5c9d8db9f265da60f5612835
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值