Python实现互斥锁解决redis缓存雪崩的问题
1、缓存雪崩
说明:redis中大量的key同时过期,导致请求大量访问数据库,数据库压力激增。
2、解决方案:
- 均匀设置过期时间
- 使用互斥锁
3、互斥锁实现
import redis
import time
# 创建Redis连接
redis_client = redis.Redis(host='localhost', port=6379, db=0)
def get_data_from_cache(key):
# 尝试从缓存中获取数据
data = redis_client.get(key)
if data is None:
# 缓存中没有数据,需要重新生成
# 获取互斥锁的名称
lock_key = f"{key}:lock"
# 尝试获取互斥锁
acquired_lock = redis_client.set(lock_key, 'locked', nx=True, ex=10)
# nx=True表示只有当锁不存在时才会设置成功,ex=10表示锁的过期时间为10秒
if acquired_lock:
# 获取到了互斥锁,生成数据并设置到缓存中
data = generate_data_fromdb()
redis_client.set(key, data, ex=60) # 设置缓存数据的过期时间为60秒
# 释放互斥锁
redis_client.delete(lock_key)
else:
# 未获取到互斥锁,先走缓存
time.sleep(0.1)
data = redis_client.get(key)
if not data:
data = generate_data_fromdb()
redis_client.set(key, data, ex=60)
else:
# 缓存中有数据,直接返回
data = data.decode('utf-8')
return data
def generate_data_fromdb():
# 模拟db操作
time.sleep(1)
return "Generated data"
# 调用示例
data = get_data_from_cache("my_key")
print(data)
说明:优先从缓存取数据,若缓存数据不存在,则尝试加锁(redis分布式锁)。
- 获取到锁的就从数据库查数据,并设置缓存,接着释放锁。
- 获取不到锁,则先睡眠0.1s,等一下获取锁的设置数据,再查缓存;若缓存还是没有,那就再查数据库。