布隆过滤器是一种空间效率极高的概率型数据结构, 由 Burton Howard Bloom 于 1970 年提出。它可以用来检测一个元素是否一定不存在或可能存在于集合中。
相比传统数据结构,内存占用极低
O(k) 时间复杂度,k 为哈希函数个数
存在假阳性,但无假阴性
布隆过滤器使用一个固定大小的位数组,初始时所有位都为 0。
使用 K 个独立的哈希函数,每个函数将元素映射到数组的不同位置:
// 例如:3个哈希函数,数组大小为32
H1("apple") = 3 → 设置 bit[3] = 1
H2("apple") = 11 → 设置 bit[11] = 1
H3("apple") = 22 → 设置 bit[22] = 1
将元素通过 K 个哈希函数,得到 K 个位置,全部设置为 1。
✅ 可能存在:所有 K 个位置都是 1
❌ 一定不存在:任意一个位置是 0
误判率 (False Positive Rate) 的公式:
// m = 位数组大小, n = 已添加元素数, k = 哈希函数个数
// 最优哈希函数个数:
k = (m / n) × ln(2)
// 误判率:
p ≈ (1 - e^(-kn/m))^k
数据库查询前先通过布隆过滤器判断,减少无效数据库访问
网页爬虫去重、邮件过滤、用户行为统计去重
LevelDB/RocksDB 使用布隆过滤器快速判断键是否存在
Google Chrome 用于检测恶意 URL
快速过滤用户已看过的内容
垃圾邮件过滤、恶意IP检测
Redis 4.0+ 支持通过 RedisBloom 模块实现布隆过滤器。
# 添加元素到布隆过滤器
BF.ADD myfilter "item1"
# 批量添加
BF.MADD myfilter "item1" "item2" "item3"
# 查询元素(返回 0 或 1)
BF.EXISTS myfilter "item1"
# 批量查询
BF.MEXISTS myfilter "item1" "item2" "item3"
# 创建带参数的布隆过滤器
# capacity: 预计元素数量
# error_rate: 期望误判率
BF.RESERVE myfilter 0.01 100000
| 命令 | 说明 | 时间复杂度 |
|---|---|---|
BF.ADD |
添加元素 | O(k) |
BF.EXISTS |
查询元素是否存在 | O(k) |
BF.MADD |
批量添加元素 | O(k×n) |
BF.MEXISTS |
批量查询元素 | O(k×n) |
BF.RESERVE |
创建过滤器并设置参数 | O(n) |
BF.INFO |
查看过滤器信息 | O(1) |
BF.SCANDUMP |
增量导出 | O(n) |
BF.LOADCHUNK |
增量导入 | O(n) |
# 使用 redis-py 与 RedisBloom
import redis
client = redis.Redis(host='localhost', port=6379)
bf = client.bf()
# 添加元素
bf.add('myfilter', 'item1')
# 批量添加
bf.add('myfilter', 'item1', 'item2', 'item3')
# 查询
exists = bf.exists('myfilter', 'item1')
# 自定义参数创建
client.bf().create('myfilter', errorRate=0.001, capacity=100000)
import hashlib
class BloomFilter:
def __init__(self, size, hash_count):
self.size = size
self.hash_count = hash_count
self.bit_array = [0] * size
def _hashes(self, item):
# 生成多个哈希值
result = []
for i in range(self.hash_count):
hash_val = hashlib.md5(f"{item}{i}".encode()).hexdigest()
result.append(int(hash_val, 16) % self.size)
return result
def add(self, item):
for pos in self._hashes(item):
self.bit_array[pos] = 1
def check(self, item):
return all(self.bit_array[pos] == 1 for pos in self._hashes(item))
| 优点 | 缺点 |
|---|---|
| ✅ 空间效率极高,比特数组占用很小 | ❌ 有假阳性(False Positive) |
| ✅ 查询效率高,时间复杂度 O(k) | ❌ 无法删除元素(删除会影响其他元素) |
| ✅ 无假阴性(False Negative) | ❌ 无法获取原始元素 |
| ✅ 并发安全,适合分布式系统 | ❌ 参数选择不当会影响效果 |
| ✅ 实现简单,易于集成 | ❌ 难以动态调整大小 |
| 类型 | 特点 | 适用场景 |
|---|---|---|
| 标准布隆过滤器 | 基本版本,存在假阳性 | 通用场景 |
| 计数布隆过滤器 | 支持删除,使用计数器 | 需要删除操作的场景 |
| 分层布隆过滤器 | 多个过滤器串联 | 减少误判率 |
| Scalable Bloom Filter | 可动态扩展 | 元素数量不可预估 |
| Cuckoo Filter | 支持删除,更高空间效率 | 需要频繁删除 |