布隆过滤器:原理、应用与误判容忍特性解析

布隆过滤器:原理、应用与误判容忍特性解析


1、论文解读

  布隆过滤器的概念最早源于1970年布隆(Bloom)发表的论文《Space/Time Trade-offsin Hash Coding with Allowable Errors》。该论文聚焦于在可容错哈希编码中寻求时间和空间复杂度之间的最佳平衡。在算法设计中,我们往往通过牺牲空间换取时间效率,或是以时间成本换取空间节省,暗示着无法同时实现最优的时间和空间效率。然而,布隆过滤器通过引入可接受的错误率这一创新概念,打破了这一传统认知,实现了在一定程度上兼顾时间和空间效率的巧妙折衷。

  布隆在文中提出了两种允许存在假阳性的数据结构,旨在高效测试一个元素是否属于特定集合。这意味着在允许少量测试元素被误识别为集合成员的前提下,可以使用更紧凑的哈希集合空间,同时保持查询速度不变。因此,对于布隆过滤器的设计,除了考量时间和空间复杂度外,还需纳入误差率作为关键因素。

  在布隆提出的两种方法中,因其时空效率更为显著,第二种方法广为人知,并被命名为“布隆过滤器”。

方法一

  与常规哈希编码相似,该方法将数据组织为一个单元数组,但其空间占用显著减小。其独特之处在于,并非将完整数据参与哈希,而是依据设定的错误率来确定参与哈希的数据量。即,当允许的错误率越低,通过哈希函数构成的单元数组所需的空间将越大。当允许错误率接近或等于(2^{-b})时,单元数组的空间可能逼近甚至等于目标数据的总大小。

  设定可接受错误率 (P),且其值位于区间 ((2^{-b}, 1)),则每个具体的 (P) 值对应一个特定大小的单元数组。例如,若选择错误率 (e) ((e > 2^{-b})),则基于此错误率计算得到一个固定大小为 (C) 比特的单元数组。如此,每个目标数据被哈希编码为一个 (C) 比特的单元数组(不保证唯一性),从而导致不同数据可能被编码为相同的单元数组,错误率即由此产生。

方法二

  这种方法摒弃了采用单一单元数组的数据结构,转而采用由N个独立哈希函数生成的位(bit)序列来表示哈希区域。初始状态下,所有哈希位均置为0。对于给定元素,通过N个哈希函数计算出各自的寻址位(如“a1、a2、a3…aN”),并将这些位对应的0值置为1。

  具体操作步骤如下:

  • 定义一个长度为N bits的哈希空间,并初始化所有位为0。
  • 选取d个不同的哈希函数,每个函数将给定元素映射到[0, N-1]范围内,并将相应位置的0置为1。
  • 对待查询元素,同样使用d个哈希函数计算其映射位置,记为“a1、a2、a3…ad”。
  • 遍历这d个位置在哈希空间中的值,若全部为1,则表明该元素可能存在于哈希空间中;若至少有一个为0,则断定该元素肯定不在哈希空间中。

  从上述步骤可以看出,该算法必然存在一定的错误率。
image.png

  图中演示了布隆过滤器的基本运作过程:

  1. 初始化一个长度为15 bits的哈希空间,所有位均为0。
  2. 使用两个哈希函数将字符串“hello”分别映射至第1位和第5位,并将这两个位设置为1。
  3. 当查询字符串“world”时,同样运用两个哈希函数计算其哈希值,得到第1位和第8位。
  4. 检查哈希空间中第1位和第8位的值,若二者均为1,则认为“world”可能存在于哈希空间;否则,判定其肯定不在。

  论文中对这两种方法进行了详细的证明,此处不再赘述。感兴趣的读者可直接查阅《Space/Time Trade-offs in Hash Coding with Allowable Errors》。

2、应用场景

  布隆过滤器作为一种高效的空间节约型数据结构,特别适用于那些需要快速判断某个元素是否可能属于一个大规模集合,同时能够容忍一定误判率的场景。

  尽管布隆过滤器无法提供精确答案,且删除操作较为困难,但其查询速度快、空间占用小的特性使其在处理海量数据、应对高并发查询以及需要进行初步过滤的场景中展现出卓越性能。在实际应用中,会根据可接受的误判率、数据规模以及性能需求等因素,综合评估是否采用布隆过滤器,并结合其他数据结构和算法以优化整体解决方案。

  典型应用场景包括

  • 缓存穿透防护

  在使用Redis等缓存系统时,频繁查询一个既不在缓存中也不在数据库中的键可能导致大量请求直接冲击数据库,形成“缓存穿透”现象。为防止此类情况,可以在缓存层前部署布隆过滤器。当接收到查询请求时,先通过布隆过滤器验证该键是否存在。若布隆过滤器判断为不存在,可立即返回,无需进一步查询缓存或数据库,有效阻断缓存穿透。虽然布隆过滤器可能出现假阳性(误判存在),但即使实际查询数据库后为空,仅带来少量额外开销,相较于缓存穿透的风险而言,这一代价是可接受的。

  • 消息去重

  在分布式消息队列系统(如RocketMQ、Kafka等)中,确保消息只被消费一次至关重要。布隆过滤器可用于检查消息的唯一标识符(如消息ID)是否已处理。消费者在接收消息后,先将消息ID提交给布隆过滤器检查。若判断为未处理,则进行消费并将其添加至布隆过滤器;若判断为已处理,则直接丢弃。即使出现少量误判(将新消息判断为已处理),通常可通过其他机制(如消息确认回执)进行修正,而整体上显著降低了重复消息的处理负担。

  • URL爬虫去重

  在网页抓取或网络爬虫应用中,避免对同一URL重复抓取是节约资源的关键。利用布隆过滤器记录已访问过的URL,每当爬虫计划抓取一个URL时,先通过布隆过滤器核实其是否已抓取。鉴于互联网URL数量之巨,布隆过滤器的空间效率使其成为理想的解决方案。尽管存在一定的误抓风险(将未抓取的URL误判为已抓取),但通常不会对整体爬取效果造成严重影响。

  • 垃圾邮件过滤

  垃圾邮件识别系统需迅速判断一封邮件是否来自已知的垃圾邮件发送者列表。面对可能包含数以亿计地址的黑名单,直接查找成本高昂。布隆过滤器可以存储黑名单地址的哈希值,当收到新邮件时,先通过布隆过滤器筛查发件人地址是否可能在黑名单内。若布隆过滤器判断为可能在黑名单,邮件会被标记为潜在垃圾邮件,进一步进行内容分析或其他精细过滤;若判断为不在黑名单,邮件则可快速放行。尽管存在误判(将正常邮件误判为垃圾邮件)或漏判(将垃圾邮件误判为正常邮件),但结合其他过滤策略,布隆过滤器有助于提高整体过滤效率。

  • 大数据预处理

  处理大规模数据集时,布隆过滤器可应用于数据清洗阶段,快速剔除明显不属于目标集合的数据。例如,在数据导入、数据分析或数据挖掘任务启动前,通过布隆过滤器筛查出可能存在的重复记录、无关项或已知异常值,从而减少后续处理所需的计算资源。

  • 推荐系统

  在推荐系统中,布隆过滤器有助于快速判断用户是否可能对某些商品或内容感兴趣。比如,根据用户的浏览历史构建一个已看过商品的布隆过滤器,当生成推荐列表时,先过滤掉用户已知的或已浏览过的商品,从而提升推荐的新鲜度和效率。


一键三连,让我的信心像气球一样膨胀!

  • 16
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乐只乐之

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值