定时与延时消息

最近更新时间: 2026-06-30 15:06:00

本文主要介绍消息队列 TDMQ RocketMQ 版中定时与延迟消息的概念和使用方式。

相关概念

  • 定时消息:消息在发送至服务端后,实际业务并不希望消费端马上收到这条消息,而是推迟到某个时间点被消费,这类消息统称为定时消息。
  • 延时消息:消息在发送至服务端后,实际业务并不希望消费端马上收到这条消息,而是推迟一段时间后再被消费,这类消息统称为延时消息。
    实际上,延时消息可以看成是定时消息的一种特殊用法,其实现的最终效果和定时消息是一致的。

使用方式

下面给出一段具体代码示例来展示如何使用 TDMQ RocketMQ 版的定时和延时消息。

定时消息

定时消息直接在 message 发送前写入标准毫秒化的时间戳到 __STARTDELIVERTIME 属性即可。

Message msg = new Message("test-topic", ("message content").getBytes(StandardCharsets.UTF_8));
// 设定消息在 2021-10-01 00:00:00 被发送
try {
    long timeStamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2021-10-01 00:00:00").getTime();
// 将 __STARTDELIVERTIME 设定到 msg 的属性中
    msg.putUserProperty("__STARTDELIVERTIME", String.valueOf(timeStamp));
    SendResult result = producer.send(msg);
    System.out.println("Send delay message: " + result);
} catch (ParseException e) {
    //TODO 添加对 Timestamp 解析失败的处理方法
    e.printStackTrace();
}

延时消息

在RocketMQ中,支持延迟消息,但是不支持任意时间精度的延迟消息,只支持特定级别的延迟消息。如果要支持任意时间精度,不能避免在Broker层面做消息排序,再涉及到持久化的考量,那么消息排序就不可避免产生巨大的性能开销。
消息延迟级别分别为1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h,共18个级别。在发送消息时,设置消息延迟级别即可,设置消息延迟级别时有以下3种情况:

  • 设置消息延迟级别等于0时,则该消息为非延迟消息。
  • 设置消息延迟级别大于等于1并且小于等于18时,消息延迟特定时间,如:设置消息延迟级别等于1,则延迟1s;设置消息延迟级别等于2,则延迟5s,以此类推。
    设置消息延迟级别大于18时,则该消息延迟级别为18,如:设置消息延迟级别等于20,则延迟2h。
Message msg = new Message("OneMoreTopic"
        , "DelayMessage", "This is a delay message.".getBytes());

//"1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h"
//设置消息延迟级别为3,也就是延迟10s。
msg.setDelayTimeLevel(3);

// 发送消息到一个Broker
SendResult sendResult = producer.send(msg);
// 通过sendResult返回消息是否成功送达
System.out.printf("%s Send Status: %s, Msg Id: %s %n"
         , sdf.format(new Date())
         , sendResult.getSendStatus()
         , sendResult.getMsgId());

// 如果不再发送消息,关闭Producer实例。
producer.shutdown();

使用限制

  • 使用延时消息时,请确保客户端的机器时钟和服务端的机器时钟(所有地域均为当地时区)保持一致,否则会有时差。
  • 定时和延时消息在精度上会有1秒左右的偏差。
  • 关于定时时间范围,最大为40天。
  • 使用定时消息时,设置的时刻在当前时刻以后才会有定时效果,否则消息将被立即发送给消费者。