什么是布隆过滤器?

93 阅读5分钟

布隆过滤器的概念和原理解释

一、布隆过滤器的基本概念

布隆过滤器是一种空间效率极高的概率性数据结构,由 Burton Howard Bloom 于 1970 年提出。它用于判断一个元素是否在集合中,但存在一定的 “误判率”(可能将不在集合中的元素误判为存在,但不会将存在的元素误判为不存在)。

二、核心原理与实现机制

1. 数据结构设计
  • 位数组(Bit Array) :底层使用一个很长的二进制数组(所有位初始为 0)。
  • 哈希函数:使用多个独立的哈希函数(如 Hash1, Hash2, ..., Hashk),将元素映射到位数组的不同位置。
2. 工作流程
  • 插入元素:对元素用每个哈希函数计算位置,将对应位设为 1。
  • 查询元素:用相同哈希函数计算位置,若所有对应位都是 1,则认为元素可能存在;若有任意一位是 0,则元素一定不存在。
3. 误判率(False Positive Rate)
  • 当位数组大小为 m,哈希函数数量为 k,插入 n 个元素时,误判率公式为:f=(1−e−mkn​)k
  • 优化目标:选择合适的 k 和 m,使误判率最小(理论最优哈希函数数量为 k=nm​ln2)。

布隆过滤器工作流程实例解析:从哈希到查询的全流程演示

一、场景设定

假设我们需要设计一个布隆过滤器来过滤恶意 URL,防止用户访问危险网站。
参数设置

  • 预期插入 URL 数量:n = 10000 个

  • 目标误判率:p = 0.01%(0.0001)

  • 计算得:

    • 位数组大小 m ≈ 184,467 位(约 23KB)
    • 哈希函数数量 k = 13 个

二、插入元素:以 URL 为例

假设要插入 3 个 URL:

  1. https://malicious-site.com/phish
  2. http://fake-bank.org/login
  3. https://evil-download.com/virus
步骤 1:哈希函数计算位置

以 13 个独立哈希函数为例(简化为 3 个哈希函数演示):

  • 哈希函数 1(MD5)

    • 对 URL1 计算:MD5("https://malicious-site.com/phish") % 184467 = 5678
    • 对 URL2 计算:MD5("http://fake-bank.org/login") % 184467 = 12345
    • 对 URL3 计算:MD5("https://evil-download.com/virus") % 184467 = 9876
  • 哈希函数 2(SHA-1)

    • URL1:SHA1(...) % 184467 = 34567
    • URL2:SHA1(...) % 184467 = 67890
    • URL3:SHA1(...) % 184467 = 23456
  • 哈希函数 3(自定义哈希)

    • URL1:custom_hash(...) % 184467 = 78901
    • URL2:custom_hash(...) % 184467 = 45678
    • URL3:custom_hash(...) % 184467 = 56789
步骤 2:标记位数组
  • 插入 URL1 时,将 56783456778901 等 13 个位置设为 1;
  • 插入 URL2 时,将 123456789045678 等位置设为 1;
  • 插入 URL3 时,将 98762345656789 等位置设为 1;

此时,位数组中被标记为 1 的位置如下(简化示意):

位索引:5678, 34567, 78901, 12345, 67890, 45678, 9876, 23456, 56789, ...(共39个位置)

三、查询元素:判断新 URL 是否恶意

假设用户访问新 URL:https://suspect-site.com/attack

步骤 1:哈希计算位置

用同样的 13 个哈希函数计算位置,假设得到:

  • hash1 = 12345(与 URL2 的哈希位置重合)
  • hash2 = 34567(与 URL1 的哈希位置重合)
  • hash3 = 56789(与 URL3 的哈希位置重合)
  • ...(其余 10 个哈希位置均被标记为 1)
步骤 2:判断存在性
  • 检查所有 13 个哈希位置,发现对应位均为 1 → 布隆过滤器返回:该 URL 可能是恶意的
  • 实际情况:该 URL 可能确实是恶意的(真阳性),也可能是误判(假阳性,即未被插入但哈希位置巧合全部被标记)。
另一种情况:查询非恶意 URL

若查询 URL:https://safe-site.com/home,其某个哈希位置计算结果为 11111,而该位置在位数组中为 0 → 布隆过滤器直接返回:该 URL 一定不是恶意的(准确判断,无漏判)。

四、误判场景演示:假阳性如何发生?

假设存在一个新 URL:https://innocent-site.com/info,它从未被插入到布隆过滤器中。
但由于哈希巧合,其 13 个哈希位置刚好全部被之前插入的 URL(如 URL1、URL2、URL3)标记为 1 → 布隆过滤器误判其为恶意 URL(假阳性)。

五、关键结论

  1. 插入逻辑:每个元素通过多个哈希函数映射到不同位置,将对应位设为 1,体现 “多哈希协同标记” 的特性。
  2. 查询逻辑:只要有一个哈希位置为 0,元素必然不存在;所有位置为 1 时,元素 “可能存在”(存在误判可能)。
  3. 误判本质:不同元素的哈希位置产生重叠(哈希冲突),导致未插入元素的所有哈希位置被其他元素 “覆盖”。

六、可视化示意(简化为 3 位哈希函数)

位数组(初始全0):[0,0,0,0,0,0,0,0,0,0,...]

插入元素A:
- 哈希1→位置2,哈希2→位置5,哈希3→位置7  
→ 位数组:[0,0,1,0,0,1,0,1,0,0,...]

插入元素B:
- 哈希1→位置5,哈希2→位置7,哈希3→位置9  
→ 位数组:[0,0,1,0,0,1,0,1,0,1,...]

查询元素C:
- 哈希1→位置5(1),哈希2→位置7(1),哈希3→位置9(1)  
→ 布隆过滤器认为C“可能存在”,但实际C未被插入(误判)。

查询元素D:
- 哈希1→位置3(0)  
→ 布隆过滤器确定D“一定不存在”。

通过这个实例可以看出,布隆过滤器的核心优势在于用极小的空间(位数组)实现快速查询,而代价是可控的误判率。在实际应用中,合理设置哈希函数数量和位数组大小,可将误判率控制在业务可接受的范围内。