基于 RocketMQ 4.2.0 版本进行的源码分析。
讲述 RocketMQ 定时消息和重试消息
一、定时消息概述
RocketMQ 支持 Producer 端发送定时消息,即该消息被发送之后,到一段时间之后才能被 Consumer 消费者端消费。但是当前开源版本的 RocketMQ 所支持的定时时间是有限的、不同级别的精度的时间,并不是任意无限制的定时时间。因此在每条消息上设置定时时间的 API 叫做 setDelayTimeLevel,而非 setDelayTime 这样的命名:
Message msg =
new Message("TopicTest" /* Topic */,
"TagA" /* Tag */,
("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */);
msg.setDelayTimeLevel(i + 1);
默认 Broker 服务器端有 18 个定时级别:
public class MessageStoreConfig {
private String messageDelayLevel = "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h";
}
这 18 个定时级别在服务器端启动的时候,会被解析并放置到表 delayLevelTable 中。解析的过程就是上述字符串按照空格拆分开,然后根据时间单位的不同再进一步进行计算,得到最终的毫秒时间。级别就是根据这些毫秒时间的顺序而确定的,例如上述 1s 延迟就是级别 1, 5s 延迟就是级别 2,以此类推:
public class ScheduleMessageService extends ConfigManager {
public boolean parseDelayLevel() {
for (int i = 0; i < levelArray.length; i++) {
// ...
int level = i + 1;
long delayTimeMillis = tu * num;
// 级别:延迟时间
this.delayLevelTable.put(level, delayTimeMillis);
}
}
}
二、定时消息预存储
客户端在为某条消息设置上定时级别的时候,实际上级别这个字段会被作为附属属性放到消息中:
public class Message implements Serializable {
public void setDelayTimeLevel(int level) {
this.putProperty(MessageConst.PROPERTY_DELAY_TIME_LEVEL, String.valueOf(level));
}
}
我们先前的文章提到过,发送到 Broker 服务器的消息会被存储到 CommitLog 消息文件中。那么在此处即使是定时消息也不例外,将定时消息存储下来是为了保证消息最大程度地不丢失。然而毕竟和普通消息不同,在遇到定时消息后,CommitLog 会将这条消息的话题和队列 ID 替换成专门用于定时的话题和相应的级别对应的队列 ID。真实的话题和队列 ID 会作为属性放置到这条消息中。
public class CommitLog {
public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
// Delay Delivery
if (msg.getDelayTimeLevel() > 0) {
topic = ScheduleMessageService.SCHEDULE_TOPIC;
queueId = ScheduleMessageService.delayLevel2QueueId(msg.getDelayTimeLevel());
// Backup real topic, queueId
MessageAccessor.putProperty(msg, MessageConst.PROPERTY_REAL_TOPIC, msg.getTopic());
MessageAccessor.putProperty(msg, MessageConst.PROPERTY_REAL_QUEUE_ID, String.valueOf(msg.getQueueId()));
msg.setPropertiesString(MessageDecoder.messageProperties2String(msg.getProperties()));
// 替换 Topic 和 QueueID
msg.setTopic(topic);
msg.setQueueId(queueId);
}
}
}
</

本文详细解读了RocketMQ4.2.0版本中关于定时消息的设置、存储、预处理以及重试策略,包括定时级别、延迟时间和消费失败后的重试流程。
最低0.47元/天 解锁文章
848

被折叠的 条评论
为什么被折叠?



