布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好得多,缺点是有一定的误识别率和删除困难。
本文章跳过其他的流程
为什么叫布隆过滤器?巴拉巴拉巴拉巴拉……
为什么叫布隆?啦吧啦吧啦吧啦吧……
……
言归正传,传正归言!开始本次分享的正题啦!
鸣人: “卡卡西老师,这个任务真的太难了,我们需要一些特别的忍术来完成它。”
卡卡西: “鸣人,有时候看似复杂的任务,只要掌握了正确的方法,其实并没有那么困难。今天我就带你了解一种特别的忍术——布隆过滤器。”
信号已接入……

布隆过滤器的基本原理
布隆过滤器由一个长度 m 位数组( bit array )和 k 个哈希函数组成:
位数组:一个固定长度的位数组,所有位初始化为0。
哈希函数:一组独立的哈希函数,每个函数将输入映射到位数组中的某个位置。
插入操作
当插入一个元素时,布隆过滤器将该元素通过 k 个哈希函数计算出 k 个位置,并将这些位置上的位设置为1。
例如,假设有三个哈希函数 ( a1 , a2 , a3 ),插入一个元素 ( x ) 时,将位数组的 ( a1(x), a2(x), a3(x) ) 位置设置为1。
查询操作
当查询一个元素是否存在时,使用同样的 k 个哈希函数计算出 k 个位置,并检查这些位置上的位是否全为1。
如果其中有一个位置为0,则该元素肯定不在集合中。
如果所有位置都为1,则该元素可能在集合中。
这里解释一下为什么说查询的时候结果为 “可能是”(Probably Yes)。
解释假阳性
比如说位数组已存储的有 ribeye 和 potato 两个值,这时候我们想查询 lemon 是否存在,于是通过哈希函数组计算哪些位上会存在1。
但在哈希函数组的计算下,不同的 k 可能会得到相同的 v (hash冲突啦)。计算并不存在的 lemon 却得到了已存在的 potato 的值,也就是说我们得到的判断是——不存在位数组中的元素 存在!( warning !warning !假阳性出现)
但是布隆过滤器肯定不会存在假阴性的!布隆过滤器有误判率,但不会漏报。只要存在,必然会存进位数组,必然能查询到!
布隆过滤器的特点总结
空间效率高
布隆过滤器使用一个位数组来表示集合,而不是存储实际的元素。位数组中的每一位只有两种状态:0或1。
通过哈希函数将元素映射到位数组的位置,以避免存储实际的元素,从而大大减少了存储空间的需求。
多个元素可以共享相同的位,这进一步提高了空间利用率。虽然这会带来假阳性问题,但总体上节省了大量的内存。
查询速度快
查询操作只需要进行几次哈希运算和位数组访问。这些操作的时间复杂度是 (O(n)),其中 n 是哈希函数的数量。
在计算机架构中,哈希运算和数组访问都非常快速,因此查询操作可以在常数时间内完成。
插入速度快
插入操作与查询操作类似,也是先通过 k 个哈希函数计算出 k 个位置,然后将这些位置的位设置为1。
由于只涉及位数组的更新和简单的哈希计算,插入操作的时间复杂度也是 (O(k)),且非常高效。
无法删除元素
标准布隆过滤器不支持删除操作,因为一次删除可能会影响到其他元素的正确性。为了支持删除,可以使用计数布隆过滤器(Counting Bloom Filter),其中每个位置存储一个计数器而不是单个位。添加元素时增加计数器,删除元素时减少计数器。
假阳性存在
当插入的元素数量增加时,位数组中的1的比例也会增加。这意味着不同元素通过哈希函数映射到同一位的概率增大。
当查询一个不存在的元素时,如果该元素的所有哈希位置都被置为1(由于其他元素的影响),布隆过滤器将返回“可能存在”。
假阳性率与位数组长度 m、哈希函数数量 k 和元素数量 n 有关。通过选择这些参数,可以控制假阳性率,但无法完全消除。
但是我们可以使用一些优化方案来减少误报率
优化
优化哈希函数数量(k)和位数组大小(m):选择适当数量的哈希函数和位数组大小可以显著降低误报率。理论上,误报率可以通过公式 计算,其中 n 是元素数量。
1、位数组长度 m:
增大 m :随着位数组长度的增加,每个哈希位置被设置为1的概率减小,从而降低假阳性率。
减小 m :如果位数组太短,则不同元素的哈希位置更容易重叠,导致更多的位被设置为1,增加假阳性率。
2、 哈希函数数量 k :
假阳性率与哈希函数数量存在一个最优点。当 k 过小或过大时,假阳性率都会增加。
过多的哈希函数:增加哈希函数数量会增加每个元素的哈希位置数目,但也会因为重复设置同一位而降效率。
过少的哈希函数:减少哈希函数数量会降低每个元素的哈希位置数目,增加假阳性率。
3、 元素数量 n :
增大 n :随着插入元素数量的增加,位数组中更多的位会被设置为1,导致假阳性率上升。
减小 n :较少的元素数量意味着位数组中更多的位将保持为0,降低假阳性率。
分布式布隆过滤器:将布隆过滤器分布在多个节点上,每个节点存储一部分位数组,可以减少单个布隆过滤器的负载,从而降低误报率。
布隆适用场景
布隆过滤器适合于那些可以容忍一定误判率的应用场景,但不适合需要百分百准确判断的场景。
主要用于快速判断元素是否可能存在于一个庞大的集合中,如缓存、垃圾邮件过滤、网页爬虫的URL去重等
缓存系统:在缓存系统中,用于快速判断一个数据是否存在于缓存中,减少不必要的数据库查询。
网络安全:用于检测恶意网址、垃圾邮件等。
区块链:用于加速区块链节点之间的同步过程。
鸣人: “卡卡西老师,原来布隆过滤器这么有用,虽然有点复杂,但掌握了之后真的很厉害!”
卡卡西: “是啊,鸣人,不论任务多难,只要掌握了正确的方法,一切问题都会迎刃而解。继续加油吧!”
如有不当之处,请评论区指正,感谢感谢
本文参考某平台博客(喻师傅)
9234

被折叠的 条评论
为什么被折叠?



