A cache stampede (also known as the thundering herd problem) occurs when multiple concurrent client requests experience a cache miss at the exact same time. This causes all requests to hit the backend database simultaneously, leading to sudden CPU spikes and database exhaustion.
Solution using Distributed Locks
By implementing a distributed lock alongside a standard Cache-Aside pattern, only the first thread that experiences a cache miss is allowed to query the database and rebuild the cached value, while subsequent concurrent requests wait or retry.
import redis
import time
# Initialize Redis client connection
r = redis.Redis(host='localhost', port=6379, db=0)
def get_cached_data(key):
# Try fetching data directly from cache
val = r.get(key)
if val:
return val.decode('utf-8')
# Try acquiring distributed lock with 10 sec timeout
lock_acquired = r.set('lock:' + key, 'true', nx=True, ex=10)
if lock_acquired:
try:
# Fetch fresh data from persistent database
data = "computed_db_result"
# Cache fresh value with 60 second TTL
r.setex(key, 60, data)
return data
finally:
# Release distributed lock safely
r.delete('lock:' + key)
else:
# Sleep briefly and retry cache lookup
time.sleep(0.1)
return get_cached_data(key)