【算法】深入理解布隆过滤器

news/2024/10/21 2:42:55/

1. 什么是布隆过滤器?

布隆过滤器(Bloom Filter)是一种空间效率极高的概率型数据结构,用于检测某个元素是否在一个集合中。与常见的数据结构如哈希表不同,布隆过滤器无法删除元素,并且会存在一定的误判率,即它可能会错误地判断一个不存在的元素为存在。

尽管如此,布隆过滤器在大规模数据场景中具有巨大的优势,特别是在存储和计算资源有限的情况下,它可以显著减少内存占用,并提供极高效的查询性能。

2. 业务场景

布隆过滤器的典型应用场景包括:

  • 缓存穿透:在分布式缓存系统中,如 Redis,如果大量不存在的数据请求直接打到数据库层,会对数据库造成较大压力。布隆过滤器可以提前过滤掉这些不存在的请求,避免数据库查询。
  • 反垃圾邮件系统:判断某个电子邮件是否曾被标记为垃圾邮件。布隆过滤器可以快速检测某个邮件是否已经处理过。
  • Web 爬虫:判断 URL 是否已经被爬取,避免重复爬取相同的页面。
  • 区块链:在比特币等加密货币中,布隆过滤器用于快速判断某个交易是否相关。

3. 布隆过滤器的原理

布隆过滤器的核心思想是使用多个哈希函数来映射数据到一个位数组中,并通过检查位数组中的对应位来判断某个元素是否可能存在。

3.1 工作流程

  1. 初始化:布隆过滤器开始时是一个长度为 m 的位数组,所有位都被设置为 0。
  2. 插入操作:当插入一个元素时,布隆过滤器会通过 k 个独立的哈希函数对该元素进行哈希运算,得到 k 个哈希值。然后将这些哈希值对应的位数组位置置为 1。
  3. 查询操作:查询时,同样使用 k 个哈希函数对元素进行哈希运算。如果所有哈希函数对应的位数组中的位置都为 1,则说明该元素可能存在;如果有任何一个位置为 0,则说明该元素一定不存在。

3.2 错误率

布隆过滤器并不能 100% 精确地判断元素是否存在,它会存在误判的可能性。即使一个元素没有插入到布隆过滤器中,它也有可能由于哈希冲突而被误认为存在。

错误率取决于:

  • 位数组的长度 m
  • 哈希函数的数量 k
  • 插入元素的数量 n

通过合理选择这些参数,可以将误判率控制在可接受的范围内。

3.3 最佳参数选择

在实际应用中,优化误判率非常重要。哈希函数的数量 k 与位数组的大小 m 有一个最佳值,通常可以通过以下公式计算:

  • 误判率P = \left( 1 - e^{-\frac{kn}{m}} \right)^k
    • P 是误判率
    • k 是哈希函数的数量
    • n 是插入的元素个数
    • m 是位数组的大小
    • e 是自然常数
  • 最佳哈希函数个数k = \frac{m}{n} \cdot \ln(2)
    • k 是哈希函数的数量
    • m 是位数组的大小
    • n 是插入的元素个数
    • ln⁡(2) 是 2 的自然对数

4. 布隆过滤器的 Python 实现

下面我们使用 Python 实现一个简单的布隆过滤器。

import mmh3  # 需要安装 mmh3 库
from bitarray import bitarray  # 需要安装 bitarray 库class BloomFilter:def __init__(self, size, hash_count):self.size = sizeself.hash_count = hash_countself.bit_array = bitarray(size)self.bit_array.setall(0)def add(self, item):for i in range(self.hash_count):digest = mmh3.hash(item, i) % self.sizeself.bit_array[digest] = 1def check(self, item):for i in range(self.hash_count):digest = mmh3.hash(item, i) % self.sizeif self.bit_array[digest] == 0:return Falsereturn True# 初始化布隆过滤器
bf = BloomFilter(size=1000, hash_count=5)# 添加元素
bf.add("hello")
bf.add("world")# 查询元素
print(bf.check("hello"))  # 输出: True
print(bf.check("python"))  # 输出: False

4.1 实现说明

  • bitarray:用于表示布隆过滤器的位数组。我们使用第三方库 bitarray,因为它比 Python 自带的 list 更加节省空间。
  • mmh3:用于计算哈希值的库。mmh3.hash(item, i) 表示对元素进行哈希运算,i 用作种子,生成不同的哈希值。

5. 布隆过滤器的扩展

5.1 可扩展布隆过滤器

当布隆过滤器的容量被填满时,误判率会急剧上升。为了解决这个问题,可以使用可扩展布隆过滤器(Scalable Bloom Filter),它通过动态增加新的布隆过滤器来保证误判率保持在设定值以下。

5.2 布谷鸟过滤器

布谷鸟过滤器是一种与布隆过滤器类似的数据结构,但它支持删除操作,并且通常具有更低的错误率。它通过布谷鸟哈希法在内存中为元素找到更合适的位置。

6. 总结

布隆过滤器是一个极具效率的数据结构,尤其适用于需要快速判断某个元素是否存在于大规模数据集中的场景。虽然它存在误判的缺点,但通过合理设置参数,可以将误判率降至较低范围。同时,布隆过滤器的轻量化和快速性使得它在缓存、爬虫、反垃圾邮件等领域得到了广泛应用。


参考

  1. Bloom Filter in Python

http://www.ppmy.cn/news/1540671.html

相关文章

市场上几个跨平台开发框架?

跨平台桌面应用开发框架是一种工具或框架,它允许开发者使用一种统一的代码库或语言来创建能够在多个操作系统上运行的桌面应用程序。传统上,开发者需要为每个操作系统编写不同的代码,使用不同的开发工具和语言。而跨平台桌面应用开发框架通过…

list(1)

list 大体上与之前学的string,vector类似&#xff0c;list不支持[]访问&#xff0c;擅长头插&#xff0c;头删&#xff0c;尾插&#xff0c;尾删&#xff0c;中间元素插入删除&#xff0c;因为list底层是双向循环带头链表 一段代码演示&#xff1a; #include <iostream>…

tftpd.exe开启调试

tftpd.exe开启调试 debugFlags设置为0xf开启debug 设置为0xf000f则开启debug和trace 第一部分&#xff1a; 位置 net/tcpip/services/tftpd/service.c if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\Tftpd\\Paramet…

【推导过程】常用离散分布的数学期望、方差、特征函数

文章目录 相关教程相关文献常用离散分布的数学期望&方差&特征函数二项分布数学期望方差 泊松分布泊松定理数学期望方差 超几何分布超几何分布的二项近似数学期望方差 几何分布几何分布的无记忆性数学期望方差 负二项分布 作者&#xff1a;小猪快跑 基础数学&计算数…

笔试练习day7

目录 OR59 字符串中找出连续最长的数字串题目解析解法(双指针遍历)代码 NC109 岛屿数量题目解析解法代码(dfs)dfs的实现 拼三角题目解析解法(枚举)代码 感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接 &#x1f412;&#x1f412;&#x1f412; 个人主页 &…

DBSwitch和Seatunel

一、DBSwitch 什么是DBSwitch?它主要用在什么场景&#xff1f; 通过步骤分析可以看到这个是通过配置数据源&#xff0c;采用一次性或定时方案&#xff0c;同步到数据仓库的指定表&#xff0c;并且指定映射关系的工具。有点类似于flinkcdc的增量同步。 参考&#xff1a; dbs…

webAPI中的排他思想、自定义属性操作、节点操作(配大量案例练习)

一、排他操作 1.排他思想 如果有同一组元素&#xff0c;我们想要某一个元素实现某种样式&#xff0c;需要用到循环的排他思想算法&#xff1a; 1.所有的元素全部清除样式 2.给当前的元素设置样式 注意顺序能不能颠倒&#xff0c;首先清除全部样式&#xff0c;再设置自己当前的…

Debian12离线部署docker详细教程

1、转至 https://download.docker.com/linux/debian/dists/ 2、在列表中选择您的 Debian 版本。 cat /etc/os-release # 我的版本号是bookworm3、转到pool/stable/并选择适用的架构&#xff08;amd64、 armhf、arm64或s390x&#xff09; 4、在deb网址下&#xff0c;下载Doc…