自顶向下学习 RocketMQ(六):定时消息

本文详细介绍了 RocketMQ 的定时消息实现原理及 Demo。定时消息在到达特定延迟时间后才会投递给消费者。文章涵盖了配置、发送、接收消息的步骤,并展示了消息如何在 SCHEDULE_TOPIC_XXXX 中按延迟级别存储,以及如何通过调度恢复并写入正确 Topic。通过示例代码,演示了如何设置延迟级别发送和接收定时消息。
摘要由CSDN通过智能技术生成

定义和原理

定时消息(延迟队列) 是指消息发送到 broker 后,不会立即被消费,等待特定时间投递给真正的 topic。

broker 有配置项 messageDelayLevel,默认值为 1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h 18 个 level , 可以配置自定义 messageDelayLevel。

注意,messageDelayLevel 是 broker 的属性,不属于某个 topic。发消息时,设置 delayLevel 等级即可:msg.setDelayLevel(level)。level 有以下三种情况:

  • level == 0,消息为非延迟消息
  • 1<=level<=maxLevel,消息延迟特定时间,例如 level==1,延迟 1s
  • level > maxLevel,则 level== maxLevel,例如 level==20,延迟 2h

定时消息会暂存在名为 SCHEDULE_TOPIC_XXXX 的 topic 中,并根据 delayTimeLevel 存入特定的 queue,queueId = delayTimeLevel – 1,即一个 queue 只存相同延迟的消息,保证具有相同发送延迟的消息能够顺序消费。broker 会调度地消费 SCHEDULE_TOPIC_XXXX,将消息写入真实的 topic。

RocketMQ 暂时不支持任意时间的定时

简化一个实现原理方案示意图:

分为两个部分:

  • 消息的写入
  • 消息的 Schedule

消息写入中:

  1. 在写入 CommitLog 之前,如果是延迟消息,替换掉消息的 Topic 和 queueId(被替换为延迟消息特定的 Topic,queueId 则为延迟级别对应的 id)
  2. 消息写入 CommitLog 之后,提交 dispatchRequest 到 DispatchService
  3. 因为在第①步中 Topic 和 QueueId 被替换了,所以写入的 ConsumeQueue 实际上非真正消息应该所属的 ConsumeQueue,而是写入到 ScheduledConsumeQueue 中(这个特定的 Queue 存放不会被消费)

Schedule 过程中:

  1. 给每个 Level 设置定时器,从 ScheduledConsumeQueue 中读取信息
  2. 如果 ScheduledConsumeQueue 中的元素已近到时,那么从 CommitLog 中读取消息内容,恢复成正常的消息内容写入 CommitLog
  3. 写入 CommitLog 后提交 dispatchRequest 给 DispatchService
  4. 因为在写入 CommitLog 前已经恢复了 Topic 等属性,所以此时 DispatchService 会将消息投递到正确的 ConsumeQueue 中

Demo

配置

由于 spring cloud alibaba 低版本的 rocketmq 定时消息功能有问题,不能实现,所以必须换高版本的,下面是我使用的版本信息:

<spring.boot.version>2.3.12.RELEASE</spring.boot.version>
<spring.cloud.version>Hoxton.SR12</spring.cloud.version>
<spring.cloud.alibab
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值