Preventing Cache Avalanche in Redis: Causes and Mitigation Strategies

Understanding Cache Avalanche

Cache avalanche refers to a scenario where a large number of cached items expire simultaneously or the cache service becomes unavailable, causing a sudden flood of requests to hit the underlying data base. This can lead to database overload, increased latency, or complete service failure.

Common Causes

  • Identical expiration times set for multiple cache entries
  • Cache server downtime or network issues
  • Unexpected traffic spikes overwhelming cache capacity

Prevention Tecnhiques

Randomized Expiration Times

Add random variations to cache expiration times to prevent simultaneous invalidation:

import random

base_expiry = 3600  # 1 hour base TTL
random_offset = random.randint(0, 300)  # 0 to 5 minutes variation
total_ttl = base_expiry + random_offset

cache_client.set("item_key", "cached_value", expire=total_ttl)

High Availability Setup

Implement Redis Cluster or Sentinel for automatic failover and data replication to avoid single points of failure.

Layered Caching Approach

Combine local in-memory cache with distributed Redis cache:

def get_cached_data(key):
    # Check local cache first
    local_value = local_cache.get(key)
    if local_value:
        return local_value
    
    # Fall back to Redis
    redis_value = redis_client.get(key)
    if redis_value:
        local_cache.set(key, redis_value, ttl=60)  # Short local TTL
        return redis_value
    
    # Acquire lock to prevent cache stampede
    lock_acquired = redis_client.set("lock:" + key, "1", nx=True, ex=10)
    if lock_acquired:
        try:
            db_data = fetch_from_database(key)
            redis_client.set(key, db_data, ex=3600)
            local_cache.set(key, db_data, ttl=60)
            return db_data
        finally:
            redis_client.delete("lock:" + key)
    else:
        time.sleep(0.1)
        return get_cached_data(key)  # Retry after delay

Rate Limiting and Fallbacks

Implement request throttling and graceful degradation when database pressure increases:

from circuitbreaker import circuit

@circuit(failure_threshold=5, recovery_timeout=30)
def protected_db_query(key):
    return database.fetch(key)

def get_data_with_fallback(key):
    try:
        return protected_db_query(key)
    except CircuitBreakerError:
        return get_default_data(key)  # Return cached or static data

Cache Preloading

Pre-populate cache with frequently accessed data during off-peak hours or before expected traffic surges.

Monitoring and Maintenance

Regularly monitor cache hit rates, expiration patterns, and data base load. Implement alerts for unusual cache behavior and conduct periodic failure simulations to validate recovery procedures.

Tags: Redis Cache Avalanche Distributed Systems High Availability

Posted on Wed, 26 Aug 2026 16:27:16 +0000 by andrewgauger