如何在Redis键过期被清理时执行额外操作?
如何在Redis缓存过期时执行额外操作
要实现Redis缓存过期时触发额外操作,最可靠的方式是利用Redis的**键空间通知(Keyspace Notifications)**功能,下面是具体实现步骤:
1. 开启Redis键空间通知
首先需要让Redis启用过期事件的通知:
- 临时生效(重启Redis后失效):在Redis客户端执行命令:
config set notify-keyspace-events Ex - 永久生效:修改Redis配置文件
redis.conf,找到notify-keyspace-events项,设置为:
其中notify-keyspace-events ExE表示启用事件通知,x表示监听键过期事件。
2. 修改Python代码实现监听
因为Redis的订阅操作是阻塞的,我们需要单独启动一个线程来监听过期事件,避免阻塞主业务逻辑。修改后的代码如下:
import redis import threading class RedisClient: db = redis.Redis(host="localhost", port=6379, db=0) @staticmethod def do_extra_on_expire(identifier): """缓存过期时执行的额外操作""" print(f"执行过期额外操作,键:{identifier}") # 在这里添加你的业务逻辑,比如更新数据库、发送通知等 @classmethod def cache_data(cls, data1, data2): identifier = "ani" pipe = cls.db.pipeline() pipe.hset(identifier, "first", data1) pipe.hset(identifier, "second", data2) pipe.expire(identifier, 3600) pipe.execute() @classmethod def start_expire_listener(cls): """启动过期事件监听线程""" def listen(): # 订阅键过期事件的频道,__keyevent@0__:expired 中的0是数据库编号,对应你使用的db=0 pubsub = cls.db.pubsub() pubsub.subscribe('__keyevent@0__:expired') for message in pubsub.listen(): # 过滤掉订阅成功的初始消息,只处理过期事件 if message['type'] == 'message': expired_key = message['data'].decode('utf-8') cls.do_extra_on_expire(expired_key) # 启动后台线程监听 listener_thread = threading.Thread(target=listen, daemon=True) listener_thread.start() # 启动监听线程 RedisClient.start_expire_listener() # 测试缓存数据 RedisClient.cache_data("test_data1", "test_data2")
关键说明
- 监听线程使用
daemon=True,这样主程序退出时线程会自动终止。 - 频道名称
__keyevent@0__:expired中的0要和你使用的Redis数据库编号一致(代码中是db=0)。 - 过期事件是在Redis实际删除过期键时触发的,这可能会比键的过期时间稍有延迟(取决于Redis的惰性删除和定期删除机制)。
备选方案(如果无法开启键空间通知)
如果因为权限或其他原因无法开启键空间通知,可以在每次获取缓存时做惰性检查:
@classmethod def get_cached_data(cls, identifier): data = cls.db.hgetall(identifier) if not data: # 缓存已过期/不存在,执行额外操作 cls.do_extra_on_expire(identifier) # 可以在这里重新加载数据到缓存 return data
这种方式的缺点是无法实时触发额外操作,只有当代码主动获取缓存时才会检查。
内容的提问来源于stack exchange,提问作者Qendrim Krasniqi
相关产品推荐
相关产品推荐

