1. What Is Bloom Filter
A Bloom Filter is a data structure proposed by Bloom in 1970.
It maps elements (x, y, z) through a series of functions into a binary vector (a 0101 sequence), and is used to quickly determine whether an element w is in a set. As shown below (from Wikipedia):
Compared with using a single mapping function, multiple mapping functions reduce the collision rate within the same address space. Therefore, at the same collision rate, multiple mapping functions require less address space than a single one.
A Bloom Filter uses a very short binary vector and achieves extremely high space efficiency by sacrificing accuracy. In large-scale data query scenarios, it effectively avoids disk IO and delivers very high query efficiency.
In fact, to determine whether an element is in a large set, you can also use a Bitmap. Convert the element to an integer x; the index value of x in the Bitmap is 0 (meaning it does not exist) or 1 (meaning it exists).
A Bloom Filter and a Bitmap are somewhat similar; both use a binary vector and mapping functions to determine whether an element exists. The difference is that a Bitmap has only one mapping function and its vector size cannot be smaller than the largest integer; a Bloom Filter has multiple mapping functions and can choose binary vectors of different sizes according to the false positive rate required by the scenario.
2. Common Application Scenarios
A Bloom Filter has a certain false positive rate and mainly solves two kinds of problems: definitely not present and possibly present.
2.1 Definitely Not Present - False
- Word spell checking. A misspelled word definitely does not exist
- Preventing database penetration. Querying rows or columns that do not exist
- Cache penetration. When nothing is found in the cache, the request penetrates to the database
2.2 Possibly Present - True
- Deduplicating URLs in a crawler. Skipping URLs that have already been crawled
- Spam filtering. Addresses on the blacklist are blocked
- Avoiding recommending duplicate articles. Skipping the URL/ID of articles already read
- Web interceptors. Blocking URL addresses on the blacklist
3. Choosing Bloom Filter Parameters
As mentioned above, a Bloom Filter can choose binary vectors of different sizes according to the false positive rate required by the scenario. In production we need to balance the false positive rate against efficiency. The formula given by Wikipedia is:
k = (m/n) ln2
where,
- m is the size of the binary vector
- n is the number of elements
- k is the number of mapping functions
- ln2 is a constant, approximately 0.69
The table below shows the false positive rate for different m/n and k.
| m/n | k | k=1 | k=2 | k=3 | k=4 | k=5 | k=6 | k=7 | k=8 |
|---|---|---|---|---|---|---|---|---|---|
| 2 | 1.39 | 0.393 | 0.400 | ||||||
| 3 | 2.08 | 0.283 | 0.237 | 0.253 | |||||
| 4 | 2.77 | 0.221 | 0.155 | 0.147 | 0.160 | ||||
| 5 | 3.46 | 0.181 | 0.109 | 0.092 | 0.092 | 0.101 | |||
| 6 | 4.16 | 0.154 | 0.0804 | 0.0609 | 0.0561 | 0.0578 | 0.0638 | ||
| 7 | 4.85 | 0.133 | 0.0618 | 0.0423 | 0.0359 | 0.0347 | 0.0364 | ||
| 8 | 5.55 | 0.118 | 0.0489 | 0.0306 | 0.024 | 0.0217 | 0.0216 | 0.0229 | |
| 9 | 6.24 | 0.105 | 0.0397 | 0.0228 | 0.0166 | 0.0141 | 0.0133 | 0.0135 | 0.0145 |
| 10 | 6.93 | 0.0952 | 0.0329 | 0.0174 | 0.0118 | 0.00943 | 0.00844 | 0.00819 | 0.00846 |
| 11 | 7.62 | 0.0869 | 0.0276 | 0.0136 | 0.00864 | 0.0065 | 0.00552 | 0.00513 | 0.00509 |
| 12 | 8.32 | 0.08 | 0.0236 | 0.0108 | 0.00646 | 0.00459 | 0.00371 | 0.00329 | 0.00314 |
| 13 | 9.01 | 0.074 | 0.0203 | 0.00875 | 0.00492 | 0.00332 | 0.00255 | 0.00217 | 0.00199 |
| 14 | 9.7 | 0.0689 | 0.0177 | 0.00718 | 0.00381 | 0.00244 | 0.00179 | 0.00146 | 0.00129 |
| 15 | 10.4 | 0.0645 | 0.0156 | 0.00596 | 0.003 | 0.00183 | 0.00128 | 0.001 | 0.000852 |
| 16 | 11.1 | 0.0606 | 0.0138 | 0.005 | 0.00239 | 0.00139 | 0.000935 | 0.000702 | 0.000574 |
| 17 | 11.8 | 0.0571 | 0.0123 | 0.00423 | 0.00193 | 0.00107 | 0.000692 | 0.000499 | 0.000394 |
| 18 | 12.5 | 0.054 | 0.0111 | 0.00362 | 0.00158 | 0.000839 | 0.000519 | 0.00036 | 0.000275 |
| 19 | 13.2 | 0.0513 | 0.00998 | 0.00312 | 0.0013 | 0.000663 | 0.000394 | 0.000264 | 0.000194 |
| 20 | 13.9 | 0.0488 | 0.00906 | 0.0027 | 0.00108 | 0.00053 | 0.000303 | 0.000196 | 0.00014 |
| 21 | 14.6 | 0.0465 | 0.00825 | 0.00236 | 0.000905 | 0.000427 | 0.000236 | 0.000147 | 0.000101 |
| 22 | 15.2 | 0.0444 | 0.00755 | 0.00207 | 0.000764 | 0.000347 | 0.000185 | 0.000112 | 7.46e-05 |
| 23 | 15.9 | 0.0425 | 0.00694 | 0.00183 | 0.000649 | 0.000285 | 0.000147 | 8.56e-05 | 5.55e-05 |
| 24 | 16.6 | 0.0408 | 0.00639 | 0.00162 | 0.000555 | 0.000235 | 0.000117 | 6.63e-05 | 4.17e-05 |
| 25 | 17.3 | 0.0392 | 0.00591 | 0.00145 | 0.000478 | 0.000196 | 9.44e-05 | 5.18e-05 | 3.16e-05 |
| 26 | 18 | 0.0377 | 0.00548 | 0.00129 | 0.000413 | 0.000164 | 7.66e-05 | 4.08e-05 | 2.42e-05 |
| 27 | 18.7 | 0.0364 | 0.0051 | 0.00116 | 0.000359 | 0.000138 | 6.26e-05 | 3.24e-05 | 1.87e-05 |
| 28 | 19.4 | 0.0351 | 0.00475 | 0.00105 | 0.000314 | 0.000117 | 5.15e-05 | 2.59e-05 | 1.46e-05 |
| 29 | 20.1 | 0.0339 | 0.00444 | 0.000949 | 0.000276 | 9.96e-05 | 4.26e-05 | 2.09e-05 | 1.14e-05 |
| 30 | 20.8 | 0.0328 | 0.00416 | 0.000862 | 0.000243 | 8.53e-05 | 3.55e-05 | 1.69e-05 | 9.01e-06 |
| 31 | 21.5 | 0.0317 | 0.0039 | 0.000785 | 0.000215 | 7.33e-05 | 2.97e-05 | 1.38e-05 | 7.16e-06 |
| 32 | 22.2 | 0.0308 | 0.00367 | 0.000717 | 0.000191 | 6.33e-05 | 2.5e-05 | 1.13e-05 | 5.73e-06 |
When using it, first decide on an acceptable false positive rate, then compute the size of the binary vector from the formula:
m = (k * n) / ln2
For example, choose a false positive rate of 0.003, k = 4, m/n = 15 . With 1 million records, the required binary vector size is ( 4 _ 10e6 ) / 0.693 ≈ 5.77 _ 10e6 bit = 704.6 KB .
4. Drawbacks of Bloom Filter
The main drawbacks of a Bloom Filter:
- Elements cannot be deleted. A single binary vector bit may correspond to the mappings of multiple elements, so it cannot simply be set to 0 .
- It applies only to single-machine systems, and memory overhead grows linearly with data scale. Some middleware already provides Bloom filters, such as Redis, which can be used for very large-scale data scenarios.
There are many algorithms that optimize on the Bloom Filter; they amount to adding redundancy to the information, but none match the Bloom Filter in efficiency. Here are a few related algorithms:
- Counting Bloom Filter
On top of the standard Bloom filter, each Bit is replaced by a counter; adding an element increments the count, and deleting an element decrements it.
- Spectral Bloom Filters
In the Counting Bloom Filter above, the counters have a fixed number of bits. Spectral Bloom Filters use dynamically sized counters, which is more flexible and avoids counter overflow.
- Compressed Bloom Filters
By reducing the number of mapping functions, it reduces the Bits transmitted over the network. In exchange for the same false positive rate, the binary vector becomes larger.
- D-left Counting Bloom Filters
Based on D-left Hashing, it reduces storage space and the false positive rate, and supports element deletion.
- Dynamic Counting Filters
Supports querying the storage frequency of an element
- Cuckoo Filter
The cuckoo algorithm differs from the Bloom filter; it imitates the cuckoo to resolve mapping collisions. When different elements map to the same bit, the last mapped element kicks out the previously mapped one.
The cuckoo algorithm supports deletion, has a space utilization of only 50 %, stores only the fingerprint of an element, and has very high query efficiency.
5. Go Implementation
Here we use github.com/willf/bloom to run a simple test of the Bloom Filter.
| |
Execution result:
| |
