Bloom Filter 是 1970 年提出的概率型數據結構,用極小空間實現大規模集合成員查詢,適用於網絡爬蟲 URL 去重、垃圾郵件過濾等場景。本文深度解析其原理、誤判率數學模型、參數優化公式、工程實戰經驗與 TBOX 庫使用示例。
m 比特位陣列(m/8+1 字節)k 個獨立雜湊函數,將元素映射到 k 個位索引k 個位置 1k 個位全為 1 → **可能存在**;任一為 0 → **絕不存在**設 n 為元素數,m 位數組大小,k 雜湊函數數。
誤判率 p = (1 - (1 - 1/m)^(kn))^k ≈ (1 - e^(-kn/m))^k
k = (m/n) * ln2 → 代入得 p = (1/2)^k → m/n = -ln(p) / (ln2)^2
理論值:
p<0.1: k=3.32, m/n=4.79
p<0.01: k=6.64, m/n=9.58
p<0.001: k=9.97, m/n=14.37
缺點:k 較大(≥4),雜湊計算開銷大,實際性能差。
作者推導靈活公式:
c = p^(1/k)
s = m/n = -k / ln(1 - c) ≈ 2k / (2c + c²)(泰勒展開近似)
| 目標 p | k | s=m/n | 空間估算 |
|---|---|---|---|
| 0.1 | 3 | 5.25 | ~6.3 MB |
| 0.01 | 3 | 12.57 | ~15 MB |
| 0.001 | 3 | 28.57 | ~34 MB |
| 0.0001 | 4 | 38.10 | ~45 MB |
結論:k=3 或 4 即可滿足大多數場景,無需追求理論最優 k。優質雜湊函數實測誤判率遠低於理論值(如 p=0.01,k=3 實測 0.0049)。
tb_size_t count = 10000000;
tb_bloom_filter_ref_t filter = tb_bloom_filter_init(
TB_BLOOM_FILTER_PROBABILITY_0_01, // 預定義誤判率 ~0.01
3, // k=3
count, // 元素規模
tb_item_func_long() // 元素類型/雜湊函數
);
if(filter) {
for(tb_size_t i=0; i
預定義誤判率常量:PROBABILITY_0_1 (2^-3)、PROBABILITY_0_01 (2^-6)、PROBABILITY_0_001 (2^-10) 等。支持自定義雜湊函數。
Java 簡易實現參考
public class SimpleBloomFilter {
private static final int SIZE = 2 << 24;
private static final int[] SEEDS = {5,7,11,13,31,37,61};
private BitSet bits = new BitSet(SIZE);
private SimpleHash[] func = new SimpleHash[SEEDS.length];
// ... add/contains 實現
}
總結
- Bloom Filter 以極小空間換取可控誤判率
- 參數選擇:實際工程中
k=3~4、按 s=m/n 表配置空間
- 雜湊函數質量直接影響實際誤判率,需精心設計
- 不支持刪除,需刪除用 Counting Bloom Filter
- TBOX 等成熟庫提供開箱即用的實現