You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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 Ex
    
    其中E表示启用事件通知,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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 07:41:06