news 2026/5/4 20:54:07

RocketMQ延迟消息实现原理解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
RocketMQ延迟消息实现原理解析

一、核心原理概述

RocketMQ的延迟消息实现采用"预置延迟等级 + 定时扫描转发"的机制,并非真正的实时延迟,就是通过预定延迟等级将消息暂存到特定队列,等待时间到达后再投递给消费者。

1. 实现方式

RocketMQ 将延时消息转换为普通消息,通过SCHEDULE_TOPIC_XXXX主题进行分级存储和消费。

2. 延迟级别

RocketMQ 一共支持18个等级的延迟投递,具体时间如下:

投递等级(delay level)延迟时间投递等级(delay level)延迟时间
11s106min
25s117min
310s128min
430s139min
51min1410min
62min1520min
73min1630min
84min171h
95min182h
// RocketMQ预定义的18个延迟等级 private String messageDelayLevel = "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h"; // 对应18个SCHEDULE_TOPIC_XXXX队列

3. 整体流程

二、核心实现步骤

发送阶段

java // 生产者发送延迟消息 Message msg = new Message("TestTopic", "Hello RocketMQ".getBytes()); // 设置延迟级别(对应上面级别的索引,从1开始) msg.setDelayTimeLevel(3); // 延迟10秒 producer.send(msg);

内部转换流程

  1. 消息标记:Broker 收到延迟消息后,将原 Topic 和 QueueId 存入消息属性

  2. 主题切换:将消息的实际 Topic 改为SCHEDULE_TOPIC_XXXX

  3. 队列分配:根据延迟级别分配到对应的延迟队列

    • 延迟级别1 → SCHEDULE_TOPIC_XXXX 的 Queue 0

    • 延迟级别2 → SCHEDULE_TOPIC_XXXX 的 Queue 1

    • ...

    • 每个延迟级别对应一个专门的队列

定时扫描机制

java // 简化后的处理逻辑 class ScheduleMessageService { // 定时任务,每秒执行一次 (实际会根据延迟级别进行分级延迟扫描) public void start() { for (int level = 1; level <= maxDelayLevel; level++) { // 计算当前级别对应的延迟时间 long delayTime = computeDeliverTimestamp(level); // 扫描对应队列中到期的消息 scanAndDeliver(level, delayTime); } } }

消息投递

  1. 扫描到期消息:每个延迟队列有独立的定时任务,按时间轮询扫描

  2. 恢复原主题:从消息属性中取出原始 Topic 和 QueueId

  3. 重新投递:将消息存入原始 Topic 的 CommitLog

  4. 消费者消费:消费者从原始 Topic 正常消费消息

三、 存储结构

四、Broker核心处理流程

五、 限制与改进

配置延迟级别

properties # broker.conf messageDelayLevel=1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h

重要限制

  1. 固定延迟级别:不支持任意时间延迟,只能使用预设级别

  2. 时间精度:秒级精度

  3. 最大延迟:默认最长2小时(可配置)

  4. 消息顺序:延迟消息会破坏严格的消息顺序

5.0+ 版本改进

RocketMQ 5.0 引入了TimerWheel(时间轮)优化:

  • 支持任意时间延迟(毫秒级精度)

  • 更高的性能,O(1) 时间复杂度

  • 支持更长的延迟时间(数天级别)

最佳实践

java // 最佳实践 public class DelayMessageExample { public void sendDelayMessage() { Message msg = new Message("OrderTopic", "订单超时取消".getBytes()); // 根据业务需求选择合适的延迟级别 // 订单超时:30分钟 → level 16 // 支付提醒:15分钟 → 可选择10m或20m级别 msg.setDelayTimeLevel(16); // 30分钟 // 消息去重:延迟消息可能需要配合唯一Key msg.setKeys("ORDER_123456"); producer.send(msg); } }

总结

RocketMQ 延迟消息通过"主题转换 + 分级延迟队列 + 定时扫描"实现,虽然不支持任意时间点延迟,但满足了大多数业务场景(如订单超时、定时提醒等)。对于更灵活的延迟需求,可考虑升级到 5.0+ 版本或使用时间轮实现。

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

day132—链表—K个一组翻转链表(LeetCode-25)

题目描述给你链表的头节点 head &#xff0c;每 k 个节点一组进行翻转&#xff0c;请你返回修改后的链表。k 是一个正整数&#xff0c;它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍&#xff0c;那么请将最后剩余的节点保持原有顺序。你不能只是单纯的改变节点内部…

作者头像 李华
网站建设 2026/5/2 5:42:20

【毕业设计】基于Java的学生身体素质测评管理系统基于SpringBoot的学生身体素质测评管理系统(源码+文档+远程调试,全bao定制等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/5/2 9:09:29

【信号处理】通过 “最近邻匹配” 和 “球面线性插值(SLERP)” 两种方式将 GNSS 位姿(位置 + 四元数)插值到激光雷达时间戳附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。&#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室&#x1f447; 关注我领取海量matlab电子书和数学建模资料 &#x1f34…

作者头像 李华
网站建设 2026/5/2 5:37:14

计算机毕设 java 基于协同过滤算法的就业推荐系统的设计与实现 基于协同过滤算法的智能就业推荐平台 求职与企业招聘匹配系统

计算机毕设 java 基于协同过滤算法的就业推荐系统的设计与实现&#xff08;配套有源码、程序、MySQL 数据库、论文&#xff09;&#xff0c;本套源码可先查看功能演示视频&#xff0c;文末有联xi 可分享c系统核心功能涵盖注册登录、个人中心、多角色管理&#xff08;管理员、用…

作者头像 李华