前置知识: 算法与数据结构

布隆过滤器

00:00
2 min Intermediate 2026/6/14

布隆过滤器(Bloom Filter)原理:哈希函数组合、误判率分析、最优参数计算与工程应用。

1. 布隆过滤器原理

1.1 基本结构

布隆过滤器是一个空间高效的概率数据结构,用于判断元素是否可能存在

位数组 m 位 + k 个独立哈希函数

添加元素 x:
  h1(x) % m → 位置设为1
  h2(x) % m → 位置设为1
  ...
  hk(x) % m → 位置设为1

查询元素 y:
  检查 h1(y), h2(y), ..., hk(y) 对应位置是否全为1
  全为1 → 可能存在(有误判率)
  有0   → 一定不存在

1.2 特性

特性说明
假阴性判断不存在 → 一定不存在
假阳性判断存在 → 可能不存在(误判)
支持删除删除可能影响其他元素
空间高效哈希表节省 10-100 倍

2. 误判率分析

2.1 数学推导

数组大小 哈希函数个数 ,已插入元素数

某个仍为 0 的概率

误判(所有 都为 1):

2.2 最优哈希函数个数

误判求导,令其为 0:

2.3 最优位数组大小

给定目标误判

2.4 常用参数表

元素数 n误判 ε最优 k数组 m内存
100万1%79.58M bit1.2 MB
100万0.1%1014.38M bit1.8 MB
1亿1%7958M bit120 MB
1亿0.01%172876M bit360 MB

3. 实现

3.1 Python 实现

import mmh3
import math

class BloomFilter:
    def __init__(self, capacity, error_rate=0.01):
        self.capacity = capacity
        self.error_rate = error_rate
        self.bit_size = self._optimal_bit_size(capacity, error_rate)
        self.hash_count = self._optimal_hash_count(self.bit_size, capacity)
        self.bit_array = bytearray(math.ceil(self.bit_size / 8))

    @staticmethod
    def _optimal_bit_size(n, p):
        return int(-n * math.log(p) / (math.log(2) ** 2))

    @staticmethod
    def _optimal_hash_count(m, n):
        return int(m / n * math.log(2))

    def _set_bit(self, index):
        byte_index = index // 8
        bit_offset = index % 8
        self.bit_array[byte_index] |= (1 << bit_offset)

    def _get_bit(self, index):
        byte_index = index // 8
        bit_offset = index % 8
        return bool(self.bit_array[byte_index] & (1 << bit_offset))

    def add(self, item):
        for seed in range(self.hash_count):
            index = mmh3.hash(str(item), seed) % self.bit_size
            self._set_bit(index)

    def contains(self, item):
        for seed in range(self.hash_count):
            index = mmh3.hash(str(item), seed) % self.bit_size
            if not self._get_bit(index):
                return False
        return True  # 可能误判

3.2 Counting Bloom Filter(支持删除)

class CountingBloomFilter:
    def __init__(self, capacity, error_rate=0.01):
        m = int(-capacity * math.log(error_rate) / (math.log(2) ** 2))
        k = int(m / capacity * math.log(2))
        self.counters = [0] * m
        self.hash_count = k
        self.bit_size = m

    def add(self, item):
        for seed in range(self.hash_count):
            idx = mmh3.hash(str(item), seed) % self.bit_size
            self.counters[idx] += 1

    def remove(self, item):
        if not self.contains(item):
            return False
        for seed in range(self.hash_count):
            idx = mmh3.hash(str(item), seed) % self.bit_size
            self.counters[idx] -= 1
        return True

    def contains(self, item):
        for seed in range(self.hash_count):
            idx = mmh3.hash(str(item), seed) % self.bit_size
            if self.counters[idx] == 0:
                return False
        return True

4. 工程应用

4.1 缓存穿透防护

# 预加载所有有效ID到布隆过滤器
bf = BloomFilter(capacity=10_000_000, error_rate=0.001)
for user_id in db.query("SELECT id FROM users"):
    bf.add(user_id)

def get_user(user_id):
    if not bf.contains(user_id):
        return None  # 一定不存在,直接返回
    # 查缓存 → 查数据库

4.2 爬虫 URL 去重

visited = BloomFilter(capacity=100_000_000)

def crawl(url):
    if visited.contains(url):
        return  # 可能已访问
    visited.add(url)
    # 爬取页面...

4.3 Redis 布隆过滤器模块

# Redis 4.0+ BF 模块
BF.RESERVE my_filter 0.001 1000000
BF.ADD my_filter "user:1001"
BF.EXISTS my_filter "user:1001"  → 1
BF.EXISTS my_filter "user:9999"  → 0

知识检测

学习进度

-- 已学文档
--% 知识覆盖率

学习推荐

专注模式