当前位置: 首页 > news >正文

Redis 过期了解

Redis 版本:5.0 : 

一:过期监听:

Spring Data Redis 封装了 Redis 的 Pub/Sub 功能,提供了对 key 过期事件的监听支持。
1. 核心类:KeyExpirationEventMessageListener
这个抽象类是 Spring 提供的,专门用于监听 Redis 的 key 过期事件。
代码中的 RedisKeyExpiredListener 继承自它

Redis 的 key 过期事件是一种发布/订阅(Pub/Sub)机制,当某个设置了过期时间的 key 被 Redis 删除时,Redis 会发布一个事件通知。Spring 通过监听这些事件,并将其封装为 Spring 事件模型中的对象,从而实现对 key 过期事件的捕获和处理

Redis 的定期删除策略是 默认每秒执行 10 次(即每 100 毫秒运行一次),这是由 Redis 配置中的 hz 参数控制的。

实际上:默认配置中,hz=10,表示每秒运行 10 次过期键清理任务。
每次运行时,Redis 会从数据库中随机选取一批设置了过期时间的键进行检查,并删除其中已过期的键。
这个过程不会扫描所有键,因此可能会有部分过期键在过期后不会立刻被删除,导致“过期键延迟删除”

可以在 redis.conf 文件中调整 hz 参数来改变 Redis 清理过期键的频率:

增大 hz 值(例如设为 20 或 30)可以提高清理频率,从而提升过期键的删除实时性,但也会增加 CPU 消耗。
减小 hz 值则节省 CPU 资源,但可能导致更多的过期键滞留内存。 

实际操作也会遇到,手动更改了TTL方便更快过期,然后不刷新Redis Manager的情况下,尽管有定期删除策略,也没有收到那几个key的过期监听 

首先来认知原理:

Redis 使用两种策略来处理设置了 TTL 的键(即有过期时间的键):

删除策略触发方式是否会触发 expired 事件
惰性删除(Lazy Expiration)key 被访问时发现已过期但未被删除(惰性删除)✅ 会触发 expired 事件
定期删除(Active Expiration)Redis 每隔一段时间扫描并随机删除部分过期键❌ 不会触发 expired 事件

public class RedisKeyExpiredListener extends KeyExpirationEventMessageListener


这个类继承自 Spring Data Redis 提供的 KeyExpirationEventMessageListener。
它监听的是 Redis 的 __keyevent@*:expired 通道。
只有当 Redis 通过惰性删除触发过期事件时,才会向这个通道发布消息,从而触发你的 onMessage() 方法。 
如果一个 key 设置了过期时间(TTL),不主动访问它,也没有在过期后被 Redis 的惰性删除机制触发,那么你确实 可能永远收不到 expired 过期通知。

疑问?

如果 Redis 通过定期删除策略已经删除了一个设置了 TTL 的 key,此时再去手动 GET 这个 key,还会触发 Redis 的 expired 过期事件吗?
答:不会触发过期事件监听器(如 RedisKeyExpiredListener)

只有在访问一个 key 时,发现它已经过期但尚未被删除的情况下,才会真正执行删除操作,并触发 expired 事件。
但如果这个 key 已经被 Redis 的定期删除机制提前删掉了:
它已经不存在于 Redis 中;此时你再访问它(如 GET my_key),会直接返回 nil;
不会再次触发 Redis 的过期检查和事件通知。

二: 那么问题来了:什么是“查询”key?什么又是“访问”key?
2.1这是关键区分点 👇

操作是否算作“访问”
GET key✅ 是
EXISTS key✅ 是
TTL key✅ 是
DEL key✅ 是
Redis 内部线程检查 key 是否存在✅ 是
Redis 定期删除时只是遍历并比较过期时间❌ 不是

所以就是代码中有对Redis进行不定时的设置复合键的key时,就会访问key,这样不用直接去手动get 此key,一样是访问到了

key格式复合键:TEST_KEY:

redisTemplate.opsForValue().set(TEST_KEY+ relatedId , null ,60, TimeUnit.SECONDS);

使用这类代码,就是会导致,如果有进行定期set,就会访问key,从而触发一些过期key的过期监听收到消息,

如果不进行设置,则一些已经过期的就有可能被定时删除而收不到消息,导致消息丢失,数据不准确的问题

另外: Redis 定期删除到底做了什么?

Redis 使用了一个叫做 activeExpireCycle() 的函数来执行定期删除。
它的大致流程如下:

void activeExpireCycle(...) {// 获取当前数据库for (j = 0; j < dbs_per_call; j++) {for (k = 0; k < keys_per_call; k++) {// 随机选取一个设置了 TTL 的 keyif (currentExpiresTime < now()) {// 直接删除,不进行任何访问操作dbDelete(db, key);}}}
}

关键点
Redis 只检查 key 的过期时间;
没有真正访问这个 key 的内容(比如读取、修改等);
所以 不会触发惰性删除逻辑;

自然也就 不会发布 expired 事件。

2.2   除了上面说的情况,某些 key 即使没手动 get,也被监听到过期事件?

模块行为是否可能访问 key
Lua 脚本EVAL 中使用 key✅ 是
集群迁移MIGRATE 命令✅ 是
持久化RDB 快照生成时❌ 否
主从同步复制 key 到从节点❌ 否
慢日志记录慢命令❌ 否
其他业务模块如缓存统计、监控工具✅ 是

所以你虽然没有显式调用 get(key),但这些模块可能会在你不察觉的情况下访问 key,从而触发惰性删除。

三:Redis 淘汰策略中访问到这个 key

场景是否触发 expired 事件
Redis 定期删除直接删掉了这个 key❌ 否
Redis 主从同步时访问了这个 key✅ 是
Redis 集群迁移该 key 到新节点✅ 是
Redis 慢日志记录了访问该 key 的命令✅ 是(说明它已经被访问)
Redis 监控工具周期性检查 key✅ 是
Redis 淘汰策略中访问到这个 key✅ 是

所以,你的 key 是如何被访问到的?

机制是否可能访问 key
Redisson 的 RLock、RLock.tryLock()✅ 是
Spring Cacheable 缓存组件✅ 是
Redis 的 SCAN 命令✅ 是
Redis 的 KEYS * 命令✅ 是
Redis 的 EXPIRE 命令✅ 是
Redis 的 DEL 命令✅ 是

这些命令虽然你不写,但 Redis 内部模块或框架库可能会使用它们。

 四:使用 Redisson 的延迟队列(推荐)

RDelayedQueue<String> queue = redisson.getDelayedQueue(redisson.getQueue("my_queue"));
queue.offer("data", 60, TimeUnit.SECONDS);// 注册监听器
queue.registerListener(item -> {log.info("收到延迟消息: {}", item);
});

这种方式比依赖 Redis 的 expired 事件更加稳定可靠。

Redis 内部模块和后台任务 可能 会访问你的 key,但这不是一定会发生的行为。
所以你看到的 key 过期事件,是 “可能触发”的结果,而不是“一定会触发”的机制。
如果你需要确保 key 过期后触发回调,请使用 Redisson 的延迟队列 或 Kafka + 定时轮询 等更可靠的机制。

http://www.xdnf.cn/news/905527.html

相关文章:

  • ​​TLV4062-Q1​​、TLV4082-Q1​​迟滞电压比较器应用笔记
  • MySQL 高级学习篇
  • 【SpringBoot自动化部署】
  • 【WebSocket】SpringBoot项目中使用WebSocket
  • 主流定位技术:Zigbee、蓝牙、UWB、RFID、5G通信介绍及对比
  • Day 41 训练
  • 鸿蒙图片缓存(一)
  • 2025年7月-12月【CISP】考试计划时间
  • 全新Xsens Animate版本是迄今为止最大的软件升级,提供更清晰的数据、快捷的工作流程以及从录制开始就更直观的体验
  • C++11 Move Constructors and Move Assignment Operators 从入门到精通
  • 现代Web安全实践:基于Token与Refresh Token的单点登录(SSO)实现
  • Java常用的判空方法
  • 数据库学习(一)——MySQL基础
  • 信息化安全与自主可控需求:国产飞腾D2000 VPX3U主板设计与实践
  • 多种风格导航菜单 HTML 实现(附源码)
  • 增量式网络爬虫通用模板
  • 嵌入式学习之系统编程(十一)网络编程之协议头,测试命令及工具
  • 可视化图解算法49:滑动窗口的最大值
  • 大话软工笔记—需求工程概述
  • day45_Tensorborad使用介绍
  • 4G网络中频段的分配
  • 进行用户VMware官网注重中一直无法登录,该怎么处理
  • Java下载文件(特殊字符编码处理)
  • 基于React + FastAPI + LangChain + 通义千问的智能医疗问答系统
  • QT: `long long` 类型转换为 `QString` 2025.6.5
  • ruoyi-plus-could 负载均衡 通过 Gateway模块配置负载均衡
  • Curtain MonGuard:智能水印颜色适配,提升屏幕信息安全
  • LabVIEW实时系统数据监控与本地存储
  • C++ 基础特性深度解析
  • 化学小工具之OpenBabel