Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

1. 基本概念

布隆过滤器(Bloom Filter)是一种空间效率很高的概率型数据结构,用于判断一个元素是否在一个集合中。它的特点是:

  • 可能存在误判(假阳性),但不会漏判(假阴性)
  • 查询速度快,与集合大小无关
  • 空间效率极高

2. 工作原理

  1. 初始化:创建一个长度为m的位数组,所有位初始化为0
  2. 哈希函数:使用k个不同的哈希函数
  3. 添加元素
    • 对元素进行k次哈希,得到k个位置
    • 将这些位置的值设为1
  4. 查询元素
    • 对元素进行k次哈希,得到k个位置
    • 如果所有位置的值都为1,则元素可能存在
    • 如果有任何一个位置为0,则元素肯定不存在

2.1. 误判率公式

布隆过滤器的误判率(假阳性概率)公式为:

1
p ≈ (1 - e^(-k * n / m))^k

其中:

  • m = 位数组大小(比特数)
  • n = 预期插入元素数量
  • k = 哈希函数数量
  • p = 误判率

2.2. 最优哈希函数数量

1
k_optimal = ln(2) * (m / n) ≈ 0.693 * (m / n)

其中:

  • m = 位数组大小(比特数)
  • n = 预期插入元素数量

3. 代码实现

BloomFilter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include <functional>
#include <memory>
#include <random>
#include <string>
#include <vector>

using namespace cutl;

class BloomFilter
{
private:
size_t size_;
bitmap bitmap_;
size_t hash_size_;

public:
BloomFilter(size_t size, size_t hash_size)
: size_(size)
, hash_size_(hash_size)
, bitmap_(size)
{
}

// 双重哈希函数,生成k个哈希值
std::pair<size_t, size_t> hash(const std::string& str) const
{
std::hash<std::string> hasher1;
std::hash<std::string> hasher2;

size_t h1 = hasher1(str);
size_t h2 = hasher2(str + "salt"); // 加盐获得不同的哈希值

return { h1, h2 };
}

/**
* 添加元素
*/
void add(const std::string& value)
{
auto pair = hash(value);
auto h1 = pair.first;
auto h2 = pair.second;
// 确保h2是奇数,提高分布性
if (h2 & 0x1 == 0) // 等同于 h2 % 2 == 0
{
h2 += 1;
}

for (size_t i = 0; i < hash_size_; ++i)
{
size_t index = (h1 + i * h2) % size_;
bitmap_.set(index);
}
}

/**
* 判断元素是否存在(可能有误判)
*/
bool contains(const std::string& value) const
{
auto pair = hash(value);
auto h1 = pair.first;
auto h2 = pair.second;
if (h2 & 0x1 == 0) // 等同于 h2 % 2 == 0
{
h2 += 1;
}

for (size_t i = 0; i < hash_size_; ++i)
{
size_t index = (h1 + i * h2) % size_;
if (!bitmap_.get(index))
{
return false;
}
}
return true;
}

/**
* 清空布隆过滤器
*/
void clear() { bitmap_.reset(); }

/**
* 获取位图中设置位的数量
*/
size_t getSetBitCount() { return bitmap_.count(); }
};

使用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void TestBsetUsage()
{
PrintSubTitle("TestBsetUsage");

// 创建布隆过滤器:位数组大小1000,使用3个哈希函数
BloomFilter bloom(1000, 3);

// 添加一些元素
bloom.add("apple");
bloom.add("banana");
bloom.add("orange");

// 测试存在性
std::cout << "Contains 'apple': " << bloom.contains("apple") << std::endl; // 应该为true
std::cout << "Contains 'banana': " << bloom.contains("banana") << std::endl; // 应该为true
std::cout << "Contains 'grape': " << bloom.contains("grape")
<< std::endl; // 可能为false,或小概率为true(误判)
}

4. 应用场景

4.1. 核心应用场景

4.1.1. 数据库与存储系统

  • 数据库查询优化:快速判断记录是否存在,避免昂贵磁盘IO
  • 键值存储系统:减少不存在的键的查找操作
  • **日志结构化合并树(LSM-Tree)**:在SSTable中快速判断键是否存在

4.1.2. 网络与缓存

  • 缓存穿透防护:防止大量请求不存在的键导致缓存击穿
  • CDN内容过滤:快速判断内容是否在边缘节点
  • 分布式缓存:减少节点间查询开销

4.1.3. 网络爬虫与去重

  • URL去重:判断URL是否已爬取,避免重复抓取
  • 内容指纹检测:检测网页内容是否重复
  • 增量爬取:只爬取新增或更新的页面

4.1.4. 网络安全

  • 恶意URL/IP检测:快速判断URL或IP是否在黑名单
  • 密码泄露检测:检查密码是否在已知泄露密码集中
  • 垃圾邮件过滤:识别已知垃圾邮件特征

4.1.5. 大数据与流处理

  • 流数据去重:在数据流中统计独立元素
  • 用户行为分析:近似统计独立用户数
  • 实时推荐系统:过滤已展示内容

4.1.6. 文件系统与存储

  • 重复数据删除:检测重复文件或数据块
  • 文件同步:快速判断文件是否需要同步
  • 备份系统:识别已备份的数据

4.1.7. 分布式系统

  • 节点路由:判断数据是否在特定节点
  • 副本检测:在分布式数据库中检测数据副本
  • 成员资格检测:判断节点是否在集群中

4.1.8. 生物信息学

  • 基因序列检测:快速查询基因序列是否存在
  • 蛋白质序列匹配:在大型数据库中搜索序列

4.2. 适用场景特征

适合使用布隆过滤器的情况:

  • 数据量巨大,内存有限
  • 可以接受一定的误判率
  • 查询性能要求高
  • 主要进行存在性检查
  • 数据为任意类型(字符串、二进制等)

不适合的情况:

  • 要求100%准确性
  • 需要删除操作
  • 数据量很小
  • 值空间有限(适合用bitmap)

5. 开源项目

5.1. common_util

Github地址: https://github.com/spencer-luo/common_util
项目概述: common_util是C++的一个通用工具库,轻量级、操作简便。common_util采用现代C++语法(C++11及以上)实现,使用cutl作为命名空间,所有接口的命名方式与STL保持一致,可以作为STL库的一个补充。

5.2. libbf

Github地址: https://github.com/mavam/libbf
项目概述: mavam提供的开源项目,C++11实现,支持多种布隆过滤器变种:
- Basic
- Counting
- Spectral MI
- Spectral RM
- Bitwise
- A^2
- Stable

5.3. bloom

Github地址: https://github.com/ArashPartow/bloom
项目概述: 轻量级、头文件库、多种哈希函数支持

评论