← 中文资源

简体中文版本

双哈希布隆过滤器

根据预期元素数和误判率计算位数组大小,使用双哈希完成成员添加与存在性检测。

阅读英文原文

功能说明

BloomFilter 是一种空间效率很高的概率数据结构:它可以明确回答“元素一定不存在”,但“可能存在”有一定误判率。实现根据预期元素数和目标误判率计算位数组长度与哈希次数,用 SHA-256 摘要拆出两个 64 位整数,再通过 h1 + i * h2 生成多个独立位置。它适合缓存穿透保护、爬虫 URL 去重、数据库键预检和大规模集合的快速排除。

位数组用 bytearray 存储,内存约为 size / 8 字节。add 设置所有对应位,in 运算符检查所有位是否都已置位。fill_ratio 返回已置位比例,可用于观察容量是否接近饱和。

关键代码

双哈希只计算一次 SHA-256,然后线性组合生成多个位置,避免为每个哈希函数重复计算摘要:

digest = hashlib.sha256(value.encode("utf-8")).digest()
first = int.from_bytes(digest[:8], "big")
second = int.from_bytes(digest[8:16], "big") or 1
for index in range(self.hash_count):
    yield (first + index * second) % self.size

第二个哈希为 0 时替换为 1,防止所有位置退化为同一个。

使用注意

布隆过滤器不支持删除单个元素,因为多个元素可能共享位;需要删除时应使用计数布隆过滤器或定期重建。插入元素超过预期数量后,误判率会迅速上升,因此应按实际规模留出余量。它只能判断“可能存在”,不能替代精确集合;对误判零容忍的场景必须再查一次真实数据源。

容量和哈希次数在构造时确定,不能动态扩容;扩容需要创建新过滤器并重新插入所有元素。空字符串会被拒绝,避免调用方误把无效键当成有效成员。重复添加同一元素会重复增加 added 计数,但不改变位状态。fill_ratio 接近 1 时说明过滤器已过饱和。

验证方式

示例以 1000 个预期元素和 1% 误判率创建过滤器,加入四个单词后检查它们全部命中,未加入的 epsilon 应返回 False。打印位数组大小、哈希次数和填充率,可确认参数计算合理。构造 BloomFilter(0) 应抛出 expected_items must be a positive integer。可以批量加入 1000 个随机词,观察填充率和误判率的变化。