news 2026/10/13 16:12:08

Redis定时任务

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Redis定时任务

“Redis 定时任务”这个概念通常有两种层面的解读:

  1. 内部原理:Redis 自身是如何管理 key 的过期时间(TTL)的?它是怎么知道并在某个时间点删除数据的?

  2. 应用实现:开发者如何利用 Redis 实现分布式的“延时队列”或“定时任务”(例如:下单 30 分钟后未支付自动取消)?

我们分别来深入讲解。


一、 Redis 内部原理:Key 的过期策略

你可能会以为当你设置EXPIRE key 60时,Redis 会给这个 key 启动一个倒计时器,时间一到就触发删除。但这在海量数据下是不可能的,因为 CPU 撑不住。

Redis 采用的是惰性删除 (Lazy Deletion)+定期删除 (Periodic Deletion)相结合的策略。

1. 惰性删除 (Lazy Deletion)
  • 原理:Redis 不会主动去盯着 key 什么时候过期。

  • 触发时机:当客户端去访问某个 key(get/set 等操作)时,Redis 会先检查:“哎,这个 key 设置了过期时间吗?过期了吗?”

    • 如果过期了:直接删除,返回nil。

    • 没过期:正常返回数据。

  • 优缺点:极其节省 CPU,但极其浪费内存。如果大量过期的 key 再也没被访问过,它们就会一直占着内存不释放。

2. 定期删除 (Periodic Deletion)

为了解决惰性删除导致的“内存泄露”问题,Redis 有一个后台周期性任务。

  • 原理:Redis 默认每秒运行 10 次(通过hz参数配置)serverCron任务。

  • 流程:

    1. 从设置了过期时间的 key 集合中,随机抽取20 个 key。

    2. 检查这 20 个 key,删除其中已过期的。

    3. 如果过期的 key 比例超过 25%,则重复步骤 1(说明过期的很多,要多删点)。

  • 限制:为了防止这个循环卡死主线程(Redis 是单线程的),它有一个执行时间上限(默认 25ms)。如果超时,立刻停止,等下一轮再说。

总结:Redis 的过期不是“准时”的,而是在访问时和后台随机抽查时清理的。


二、 应用实现:基于 Redis 的定时任务(延时队列)

这是开发者最关心的部分。假设你要做“订单 30 分钟自动关闭”,在 NestJS 或其他后端中,怎么用 Redis 实现?

方案 1:Redis ZSet (Sorted Set) ——最推荐、最主流

这是实现分布式延时队列的标准做法。

  • 原理:利用 ZSet 的Score来存储任务的执行时间戳。

  • 数据结构:

    • Key:delay_queue

    • Score:Date.now() + 30 * 60 * 1000(未来执行的时间戳)

    • Member:Order ID(或任务的 JSON 数据)

  • 执行流程 (轮询 Loop):

    1. 消费者 (Consumer)每秒(或几百毫秒)轮询 Redis。

    2. 执行命令ZRANGEBYSCORE delay_queue 0 <当前时间戳> LIMIT 0 1。

      • 意思是:把“截止到现在应该执行的任务”拿出来 1 个。

    3. 如果拿到了任务:

      • 原子性移除:使用ZREM移除该任务(防止重复执行)。

      • 注意:在多实例并发下,通常建议使用Lua 脚本将ZRANGE和ZREM原子化,确保只有一个消费者抢到任务。

    4. 处理业务逻辑(如关闭订单)。

  • 优点:精度高,支持海量任务,原生支持排序。

  • 缺点:消费者需要不断轮询(Polling),空转时会增加 Redis QPS。

订单 30 分钟自动关闭的具体实现流程:

假设现在是12:00,用户下了一个单order_1001。

第一步:生产者入队 (ZADD)用户下单成功后,代码往 Redis 里写一条记录:

  • 命令:ZADD delay_queue <12:30的时间戳> "order_1001"

  • 含义:“Redis 帮我记一下,order_1001 这个单子,要在 12:30 处理。”

  • 注意:这时候数据是存在的,不是等它消失。

第二步:消费者轮询 (ZRANGEBYSCORE)你有一个后台死循环脚本(Consumer),每秒钟问一次 Redis。

  • 12:01 问:“Redis,有没有分数 <= 12:01的订单?”

    • Redis:没有。

  • 12:29 问:“Redis,有没有分数 <= 12:29的订单?”

    • Redis:没有。(因为 order_1001 的分数是 12:30)

  • 12:30:01 问:“Redis,有没有分数 <= 12:30:01的订单?”

    • Redis:“有!order_1001 的分数是 12:30,它到期了!”

第三步:执行并删除 (ZREM)消费者拿到了order_1001:

  1. 去数据库查一下这个订单支付没有?

  2. 没支付 -> 执行关单逻辑。

  3. 已支付 -> 忽略。

  4. 关键:从 Redis 里删掉这行记录 (ZREM delay_queue "order_1001"),防止下一秒又把它取出来重复执行。

方案 2:Redis KeySpace Notifications (键空间通知) ——不推荐

Redis 有一个功能:当 Key 过期被删除时,发布一个 Pub/Sub 事件。

  • 原理:

    1. 开启配置notify-keyspace-events Ex。

    2. 设置SET order_123 "data" EX 1800(30分钟过期)。

    3. 应用订阅__keyevent@0__:expired频道。

    4. 当 key 过期消失时,应用收到通知,解析 key 里的 ID,去关单。

  • 为什么极其不推荐?

    1. 不可靠:Redis 的 Pub/Sub 是“发后即忘”的。如果你的服务刚好重启了,或者网络抖动了一下,这个“过期事件”就丢了,Redis 不会重发。你的订单就永远关不掉了。

    2. 不准时:结合第一部分说的“定期删除”原理,一个 key 过期了,可能很久之后才会被 Redis 的随机算法抽中并删除,此时才会发通知。延迟可能高达数分钟。

方案 3:Redisson DelayedQueue (Java/Node 生态封装)

如果你不想手写 ZSet 的轮询逻辑,很多客户端库(如 Java 的 Redisson,或者 Node.js 的 BullMQ)封装好了。

  • 原理:它是ZSet + Pub/Sub的结合体。

    • 数据存在 ZSet 里。

    • 客户端一旦有新任务加入,或者有任务即将到期,会通过 Pub/Sub 通知消费者“醒醒,干活了”。

    • 这样避免了 ZSet 方案中高频率空轮询的 CPU 浪费。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/12 20:36:16

GPT-SoVITS训练过程可视化:理解模型收敛状态

GPT-SoVITS训练过程可视化&#xff1a;理解模型收敛状态 在个性化语音合成的浪潮中&#xff0c;一个核心挑战始终存在&#xff1a;如何用最少的数据&#xff0c;还原最真实的声音&#xff1f;传统TTS系统往往依赖数小时高质量录音才能产出自然语音&#xff0c;这显然不适用于普…

作者头像 李华
网站建设 2026/10/11 10:39:51

【Python办公自动化】多目录文件某列透视

目录 批量处理 Excel/CSV 数据的利器:基于 Python 和 PyQt5 的目录数据分析工具 🔍 工具概览 🛠️ 技术栈 💻 核心代码解析 1. 支持拖拽的列表控件 (`FileDropWidget`) 2. 后台分析线程 (`AnalysisWorker`) 3. 主窗口逻辑 (`MainWindow`) 🚀 如何使用 完整代码 📝 总…

作者头像 李华
网站建设 2026/10/11 22:02:25

Open-AutoGLM爬虫部署全流程:从环境搭建到高并发优化(稀缺实战文档)

第一章&#xff1a;Open-AutoGLM爬虫的核心机制解析Open-AutoGLM 是一种基于大语言模型驱动的智能网页数据提取工具&#xff0c;其核心机制融合了动态页面渲染、语义理解与自动化交互能力。该系统能够在无明确API接口的环境下&#xff0c;自主识别页面结构并精准抽取目标内容&a…

作者头像 李华
网站建设 2026/10/10 6:58:21

多旋翼无人机组合导航系统-多源信息融合算法附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。&#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室&#x1f34a;个人信条&#xff1a;格物致知,完整Matlab代码获取及仿真…

作者头像 李华