Redis Bloom Filters
A Bloom filter answers one question quickly: "Have I seen this item before?" It uses a very small amount of memory and never forgets an item you added. The trade-off is a small chance of a false "yes." A "no" answer is always correct.
The Club Bouncer Analogy
A bouncer glances at a short list of tell-tale features for each member. If a visitor lacks even one feature, the bouncer knows for sure that the person is not a member. If the visitor has all the features, the bouncer says "probably a member" and checks more closely. A Bloom filter behaves like that bouncer.
Question: Is "asha99" taken? Bloom filter says NO → Definitely not taken. Skip the database. Bloom filter says YES → Probably taken. Confirm in the database.
How It Works
The filter holds a long row of bits, all set to 0. Each added item runs through several hash functions that pick bit positions. Redis turns those bits to 1. A lookup runs the same hash functions and checks the bits.
Add "asha": hash → positions 2, 7, 11 Bits: 0 0 1 0 0 0 0 1 0 0 0 1
Add "ravi": hash → positions 4, 7, 9 Bits: 0 0 1 0 1 0 0 1 0 1 0 1
Check "meena": positions 1, 4, 10
bit 1 is 0 → definitely NOT added
Check "zoya": positions 2, 4, 9
all bits are 1 → "probably added" (could be a false alarm)
Different items can set overlapping bits, which causes false positives. No operation turns a bit back to 0, so false negatives never happen.
Creating and Using a Filter
127.0.0.1:6379> BF.RESERVE usernames 0.01 100000 OK 127.0.0.1:6379> BF.ADD usernames "asha99" (integer) 1 127.0.0.1:6379> BF.EXISTS usernames "asha99" (integer) 1 127.0.0.1:6379> BF.EXISTS usernames "ravi21" (integer) 0 127.0.0.1:6379> BF.MADD usernames "meena7" "zoya3" 1) (integer) 1 2) (integer) 1
BF.RESERVE takes an error rate and an expected item count. The example allows a 1 percent false positive rate for 100,000 items. BF.ADD returns 1 when the item is new and 0 when the filter believes it already exists.
Memory Savings
Method 1 million user names ──────────────────────── ───────────────────────── Redis Set (store names) tens of megabytes Bloom filter (1% error) about 1.2 megabytes
Roughly ten bits per item deliver a 1 percent error rate, and lowering the error rate raises the bits per item.
Related Structures
- Cuckoo filter: works like a Bloom filter and supports deleting items with CF.DEL.
- Count-min sketch: estimates how many times an item appeared.
- Top-k: keeps the most frequent items from a stream, such as the ten most searched words.
127.0.0.1:6379> TOPK.RESERVE trending 3 OK 127.0.0.1:6379> TOPK.ADD trending "redis" "python" "redis" "sql" "redis" 127.0.0.1:6379> TOPK.LIST trending 1) "redis" 2) "python" 3) "sql"
Practical Example – Fast User Name Check
Sign-up form asks: "Is this user name free?" Step 1: App calls BF.EXISTS usernames "newuser" Step 2: Reply 0 → name is free. Skip the database lookup. Step 3: Reply 1 → name may be taken. Query the database to confirm. Step 4: After a real sign-up, app calls BF.ADD usernames "newuser" Result: Most checks finish in Redis, and the database sees far fewer queries.
When Not to Use a Bloom Filter
- You must list or read back the stored items.
- A false positive causes harm and you have no second check.
- You need to delete items often. Choose a Cuckoo filter instead.
Key Points
- A Bloom filter reports "definitely no" or "probably yes."
- BF.RESERVE sets error rate and size, BF.ADD inserts, and BF.EXISTS checks.
- Memory use stays tiny compared with a Set.
- Cuckoo filters, count-min sketch, and top-k solve neighboring problems.
