Mastering Redis: Solving Cache Penetration, Breakdown, and Avalanche
This article explains three common Redis cache issues—penetration, breakdown, and avalanche—detailing their causes and offering practical solutions such as parameter validation, empty-value caching, Bloom filters, mutex locks, and staggered expiration to keep systems reliable under heavy load.
Redis Interview Questions Overview
How to solve cache penetration?
How to handle cache breakdown?
How to mitigate cache avalanche?
Cache Penetration
Cache penetration occurs when a request queries data that is absent from both cache and database, causing every request to hit the database and potentially overload it. Since the data does not exist, the cache cannot store a value.
Typical reasons include limited cache capacity and the 80/20 rule where only a small fraction of data is hot.
Solutions:
Interface parameter validation: reject malformed or obviously invalid keys early.
Cache empty values: store a short‑lived placeholder for missing keys to prevent repeated DB hits, while monitoring null‑value accumulation.
Bloom filter: pre‑filter requests using a probabilistic data structure that quickly discards keys known to be absent.
Bloom filter works by hashing the key with multiple hash functions and setting the corresponding bits in a bitset. During a lookup, if any of the bits are 0 the key is definitely absent; if all are 1 the key is probably present.
The Bloom filter consists of a bitset and a set of hash functions. When adding a key, each hash function computes an index, and the bits at those indices are set to 1.
Querying follows the same hash process; if any corresponding bit is 0 the key is absent, otherwise it is considered present (with a small false‑positive probability).
Cache Breakdown
Cache breakdown happens when a hot key expires and many concurrent requests miss the cache, causing a sudden surge of DB queries.
Solutions:
Mutex lock (e.g., a ReentrantLock) so that only the first request queries the DB and populates the cache, while others wait.
static Lock reenLock = new ReentrantLock();
public List<String> getData04() throws InterruptedException {
List<String> result = new ArrayList<>();
result = getDataFromCache();
if (result.isEmpty()) {
if (reenLock.tryLock()) {
try {
System.out.println("Got lock, fetch from DB and cache");
result = getDataFromDB();
setDataToCache(result);
} finally {
reenLock.unlock();
}
} else {
result = getDataFromCache();
if (result.isEmpty()) {
System.out.println("Did not get lock, cache empty, sleep briefly");
Thread.sleep(100);
return getData04(); // retry
}
}
}
return result;
}Another approach is to keep hotspot data from expiring (e.g., top‑1000 keys) and update them asynchronously.
Cache Avalanche
Cache avalanche occurs when many keys share the same expiration time and expire simultaneously, causing a massive influx of DB requests.
Solutions:
Stagger expiration times by adding a random offset to each key's TTL.
Keep hotspot data from expiring and refresh it asynchronously.
Apply mutex locks similar to the cache breakdown solution, ensuring only one thread recomputes a missing key.
Source: https://www.jianshu.com/p/9da8133be99f
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.
Java High-Performance Architecture
Sharing Java development articles and resources, including SSM architecture and the Spring ecosystem (Spring Boot, Spring Cloud, MyBatis, Dubbo, Docker), Zookeeper, Redis, architecture design, microservices, message queues, Git, etc.
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.
