Prevent Redis Cache Penetration, Breakdown, and Avalanche Using Bloom Filters
This article explains common Redis cache problems—penetration, breakdown, and avalanche—detailing their causes, practical mitigation techniques such as request validation, caching empty results, Bloom filters, mutex locks, high‑availability setups, and provides Java code examples for implementing these solutions.
1. Cache Penetration
Cache penetration occurs when requests target keys that are absent in both the cache and the database, potentially allowing attackers to overload the database.
Common Solutions
Validation interception: perform basic checks (e.g., reject IDs <= 0) at the API layer.
Cache empty data: store a short‑lived placeholder when a database query returns no result, preventing repeated DB hits.
Bloom filter: use a probabilistic data structure that quickly indicates non‑existence of a key, reducing unnecessary DB queries.
public Student getStudentsByID(Long id) {
// Retrieve from Redis
Student student = redisTemplate.opsForValue().get(String.valueOf(id));
if (student != null) {
return student;
}
// Query DB and cache the result
student = studentDao.selectByStudentId(id);
if (student != null) {
redisTemplate.opsForValue().set(String.valueOf(id), student, 60, TimeUnit.MINUTES);
} else {
// Cache null to avoid repeated DB hits
redisTemplate.opsForValue().set(String.valueOf(id), null, 60, TimeUnit.SECONDS);
}
return student;
}The Bloom filter works in O(1) time, using multiple hash functions to set bits; if any corresponding bit is 0, the key definitely does not exist.
Note: BloomFilter does not support deletion because clearing a bit could affect other keys that share the same bit.
2. Cache Breakdown
Cache breakdown happens when hot data expires and many concurrent requests simultaneously miss the cache, causing a sudden surge of DB queries.
Solutions
Set hot data to never expire.
Use a mutex lock: only one thread fetches from the DB while others wait, though this may reduce throughput.
public String get(key) {
String value = redis.get(key);
if (value == null) { // cache miss
// Set a short lock to avoid race conditions
if (redis.setnx(key_mutex, 1, 3 * 60) == 1) { // lock acquired
value = db.get(key);
redis.set(key, value, expire_secs);
redis.del(key_mutex);
} else {
// Another thread is loading the value; retry after a short pause
sleep(50);
return get(key);
}
}
return value;
}3. Cache Avalanche
A cache avalanche occurs when a large portion of cached data becomes unavailable at once, causing massive DB traffic that can overload CPU and memory, potentially crashing the system.
Redis cluster experiences a widespread failure.
Cache becomes inaccessible, but many requests still try to read from it.
Failed cache requests fall back to the database.
The combined load on DB and Redis leads to a system‑wide collapse.
Mitigation Strategies
Pre‑incident: Deploy high‑availability cache solutions such as Redis Sentinel or Redis Cluster to survive node or data‑center failures.
During incident: Implement cache degradation or fallback mechanisms (e.g., Hystrix) that circuit‑break, limit traffic, and provide degraded responses while keeping the database alive.
Post‑incident: Perform Redis backup restoration and rapid cache warm‑up to recover normal performance.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
ITPUB
Official ITPUB account sharing technical insights, community news, and exciting events.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
