如何通过Redis发布订阅实现分布式定时任务的触发_结合过期事件通知

雨晨大大_7769

雨晨大大_7769

2026-06-02

919人浏览

原创

redis过期事件通知不精确且不可靠,因依赖惰性与定期删除混合策略,存在延迟、消息丢失、重复触发等问题,不能单独用于生产级定时任务,需配合zset轮询等兜底机制。

如何通过redis发布订阅实现分布式定时任务的触发_结合过期事件通知

Redis 的 __keyevent@*__:expired 事件通知不是“定时器”,它只在 key 真正过期时才触发,而 Redis 过期本身不精确——你设了 5 秒,实际可能延迟几十毫秒甚至几秒才发通知,尤其在高负载或低频访问场景下。

为什么不能直接用 SET + EXPIRE + __keyevent@0__:expired 做任务调度

因为 Redis 的过期是惰性+定期删除混合策略,EXPIRE 只是“标记过期时间”,不代表到点就删、就发事件。常见现象包括:

  • 你 SET task:123 "run" EX 10,但 12 秒后才收到 __keyevent@0__:expired 消息
  • 服务刚启动时订阅了频道,但中间网络抖动断连 3 秒,这期间发生的过期事件永远丢失(Redis Pub/Sub 不保证消息可达)
  • 多个实例同时订阅同一频道,一个过期 key 触发 N 次处理(没做幂等校验)
  • CONFIG SET notify-keyspace-events Ex 没生效,或者配成了 KEA 却误以为只监听 expired,结果收到一堆 del、set 干扰事件

必须显式开启并验证 notify-keyspace-events 配置

运行时配置只对当前实例生效,重启即失效;生产环境务必写入 redis.conf。验证是否生效,别只看 CONFIG GET notify-keyspace-events 返回 Ex,要实测:

Redis Skill - 高性能缓存管理
Redis Skill - 高性能缓存管理

Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。

下载
  • 开两个 redis-cli:一个执行 PSUBSCRIBE __keyevent@0__:expired
  • 另一个执行 SET test_trigger "x" EX 3
  • 3 秒后第一个窗口是否收到 pmessage?没收到就说明配置未生效或数据库编号不对(比如你用的是 db 2,就得订阅 __keyevent@2__:expired)
  • 注意:Docker 或云 Redis(如阿里云、腾讯云)默认关闭该功能,且部分托管服务禁止 CONFIG SET,需在控制台开启“键空间通知”开关

Spring Boot 中监听过期事件的坑点

Spring Data Redis 提供的 KeyExpirationEventMessageListener 是个便利封装,但它默认监听所有 DB 的所有过期事件,且不做 key 名过滤。真实业务中你通常只关心 task: 或 order: 开头的 key,否则会把缓存、Session 等无关过期也拉进来处理:

  • 不要直接继承 KeyExpirationEventMessageListener 后重写 onMessage 却忽略 message.getChannel(),它返回的是原始字节,需用 new String(message.getBody()) 解析 key 名
  • 推荐手动注册 PatternTopic("__keyevent@*__:expired"),并在回调里先判断 if (key.startsWith("task:")) { ... }
  • 监听器 Bean 必须是单例(@Scope("singleton")),否则容器可能创建多个实例,导致重复消费
  • 如果用了 Redis 集群,__keyevent@*__:expired 只在 key 所在 slot 的节点上触发,订阅必须覆盖所有 master 节点(Spring 默认只连一个节点,需配置 LettuceClientConfigurationBuilderCustomizer 或改用集群模式监听)

过期事件 ≠ 定时任务,必须补足可靠性短板

单纯依赖 expired 事件无法构建生产级定时任务,它只是“尽力通知”。真正可用的方案得叠加补偿机制:

  • 写任务时,除了 SET task:123 "payload" EX 60,还要往 zset 里加一条:ZADD task_delay_queue 1748238180 task:123(时间戳为绝对秒数)
  • 另起一个低频轮询线程(比如每 30 秒扫一次 ZRANGEBYSCORE task_delay_queue -inf now),捞出已到时间的任务,用 Lua 脚本原子地 ZREM + 处理,并确保只被一个实例抢到
  • 事件监听器收到 expired 后,仅作快速路径处理;若失败或未收到,则靠 ZSET 轮询兜底——两者是“快慢双通道”,不是二选一
  • 所有任务处理逻辑必须可重入:同一个 task:123 可能被事件触发一次、又被 ZSET 扫描触发一次,状态更新要用 SETNX 或 Lua 校验再执行

最易被忽略的一点:Redis 本身不保证过期事件 100% 发出。如果你的任务要求“严格准时”,比如金融结算倒计时,别碰这个方案——换 Quartz + 数据库时间轮,或者用 Redis Stream + consumer group 做带 ACK 的延迟队列。

相关专题

更多
什么是分布式
什么是分布式

分布式是一种计算和数据处理的方式,将计算任务或数据分散到多个计算机或节点中进行处理。本专题为大家提供分布式相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

1933

5

分布式和微服务的区别
分布式和微服务的区别

分布式和微服务的区别在定义和概念、设计思想、粒度和复杂性、服务边界和自治性、技术栈和部署方式等。本专题为大家提供分布式和微服务相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.07

2714

5

常用的数据库软件
常用的数据库软件

常用的数据库软件有MySQL、Oracle、SQL Server、PostgreSQL、MongoDB、Redis、Cassandra、Hadoop、Spark和Amazon DynamoDB。更多关于数据库软件的内容详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.02

4249

19

内存数据库有哪些
内存数据库有哪些

内存数据库有Redis、Memcached、Apache Ignite、VoltDB、TimesTen、H2 Database、Aerospike、Oracle TimesTen In-Memory Database、SAP HANA和ache Cassandra。更多关于内存数据库相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.14

3735

11

mongodb和redis哪个读取速度快
mongodb和redis哪个读取速度快

redis 的读取速度比 mongodb 更快。原因包括:1. redis 使用简单的键值存储,而 mongodb 存储 json 格式的数据,需要解析和反序列化。2. redis 使用哈希表快速查找数据,而 mongodb 使用 b-tree 索引。因此,redis 在需要高性能读取操作的应用程序中是一个更好的选择。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.02

6732

6

redis怎么做缓存服务器
redis怎么做缓存服务器

redis 作为缓存服务器的答案:redis 是一款开源、高性能、分布式的键值存储,可作为缓存服务器使用。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

623

6

redis怎么解决数据一致性
redis怎么解决数据一致性

redis 提供了两种一致性模型,以维护副本数据一致性:强一致性 (sync) 确保写操作仅在复制到所有从节点后才完成;最终一致性 (async) 则在主节点上写操作后认为已完成,牺牲一致性换取性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

736

6

mysql和redis怎么保证双写一致性
mysql和redis怎么保证双写一致性

确保 mysql 和 redis 双写一致性的技术包括:1、事务性更新:同时更新 mysql 和 redis,保证一致性;2、主从复制:mysql 主服务器更改同步到 redis 从服务器;3、基于事件的更新:mysql 记录更改并发送到 redis等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

6282

6

redis缓存一般存些什么数据
redis缓存一般存些什么数据

redis缓存中存储的数据类型包括:字符串、哈希、列表、集合、有序集合、位图、地理空间数据和hyperloglog。这些数据类型适用于存储各种数据,从简单信息到复杂对象和地理位置。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

1140

6

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
phpEnv手册
phpEnv手册

共0课时 | 0人学习

进程与SOCKET
进程与SOCKET

共6课时 | 0.5万人学习