缓存雪崩是Python后端服务使用Redis等缓存时经常面临的风险。当大量缓存键在同一时刻过期,或者缓存服务整体不可用时,瞬时请求会全部穿透到数据库,造成连接耗尽和响应变慢。下面介绍几种在Python项目中容易落地的预防方案。

错开缓存过期时间
最基础的方案是为缓存设置随机的过期时间,避免集体失效。我们可以在基础过期时间上增加一个随机值。
import redis
import random
r = redis.Redis(host='127.0.0.1', port=6379, db=0)
def set_cache(key, value, base_ttl=300):
# 基础300秒,再加0到120秒随机
ttl = base_ttl + random.randint(0, 120)
r.setex(key, ttl, value)
def get_cache(key):
return r.get(key)
使用互斥锁防止并发重建
当缓存失效时,多个线程可能同时查询数据库并写回缓存。通过Redis的setnx实现简单互斥锁,让只有一个线程去加载数据。
import redis
import time
r = redis.Redis(host='127.0.0.1', port=6379, db=0)
def get_data_with_lock(key, load_from_db, expire=300):
data = r.get(key)
if data is not None:
return data
# 尝试获取锁
lock_key = key + '_lock'
if r.setnx(lock_key, 1):
r.expire(lock_key, 10)
try:
data = load_from_db()
r.setex(key, expire, data)
finally:
r.delete(lock_key)
return data
else:
# 未获锁则短暂等待后重试
time.sleep(0.1)
return get_data_with_lock(key, load_from_db, expire)
多级缓存与限流降级
可以在Python进程内使用字典或functools.lru_cache作为本地缓存,减少Redis压力。同时结合限流,在数据库压力大时直接返回默认值。
| 方案 | 作用 |
|---|---|
| 随机TTL | 分散失效时间 |
| 互斥锁 | 避免重复查库 |
| 本地缓存 | 降低远程依赖 |
小结
预防缓存雪崩的核心是把失效和重建过程打散,并准备好兜底手段。以上Python示例可以直接集成到业务代码中,显著提升缓存层的健壮性。