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分布式锁)。

  1. 获取到锁的就从数据库查数据,并设置缓存,接着释放锁。
  2. 获取不到锁,则先睡眠0.1s,等一下获取锁的设置数据,再查缓存;若缓存还是没有,那就再查数据库。