redis淘汰机制不触发发布订阅,因淘汰是纯内存后台行为且无钩子;唯一可拦截的窗口是过期键清理路径;需通过ttl+scan主动扫描即将过期key并续期、归档或推送至mq。

Redis 淘汰前无法自动触发发布订阅
Redis 的内存淘汰(如 volatile-lru、allkeys-lfu)是纯内存层面的后台行为,不带任何钩子或回调。它不会在 key 被驱逐前主动执行 PUBLISH、调用 Lua 脚本,更不会帮你推到 MQ。所谓“淘汰前兜底”,本质是误读了淘汰机制的触发时机和可控性。
真正能拦截淘汰动作的只有过期键清理路径
Redis 对“过期”和“淘汰”做了严格区分:
- 过期键(有
EXPIRE/PEXPIREAT)走的是惰性 + 定期删除,这部分逻辑可被间接观测; - 淘汰(
maxmemory触发)是 LRU/LFU/Random 等策略直接从候选集里选 key 并释放内存,全程无事件、无日志、不可中断。
所以,想“在淘汰前推送”,唯一可行的窗口是:你主动控制哪些 key 该被淘汰,并在它被淘汰前手动做兜底。这需要你放弃依赖 Redis 自动淘汰,转为自行管理生命周期。
Redis 8.2.3 是一款安全优先的高性能键值存储系统。该版本紧急修复了可能引发远程代码执行(RCE)的高危漏洞(CVE-2025-62507),并解决了 HyperLogLog 及 Cuckoo Filter 等数据结构在特定场景下的崩溃问题。建议所有用户立即升级,以保障生产环境的系统稳定与数据安全。
替代方案:用 TTL + 定时扫描 + 主动续期/归档
-
TTL命令能查出 key 剩余秒数,但返回-2表示已过期(尚未被惰性或定期删除),-1表示永不过期; - 你可以用
SCAN配合TTL批量扫描即将过期(比如 - 调用
EXPIRE续期(适用于用户活跃场景,如 token) - 读取 value 后发到 Kafka/RabbitMQ(注意避免重复推送,需幂等设计)
- 写入归档表或落盘,标记为“已兜底”,后续淘汰就无所谓了
KEYS *,它会阻塞主线程;SCAN 是唯一安全的选择。别踩的坑:监听 __keyevent@*__:expired 不能覆盖淘汰场景
这个频道只广播由过期机制触发的删除事件(即惰性或定期删除真正删掉 key 时),而 noeviction 或 allkeys-lru 淘汰的 key 根本不会触发该事件——它们压根没设过期时间。很多团队误以为订阅这个就能兜住所有“消失的 key”,结果线上出问题才发现漏了大半。
真正要兜住“计算型数据”,得从应用层设计:把需要后续计算的 key 显式打标(比如加 :calc 后缀)、统一用 EXPIREAT 设置逻辑过期时间、再配一个独立的归档服务轮询这些 key。Redis 本身,只负责快和稳,不负责“临终托付”。










