RocketMq 延时队列
- 延时队列
先说一下,基本的概念,什么是延时队列,实际的业务场景就是,一个人下订单后多久没有支付,然后取消订单,这个多久就是延时,这个逻辑可以用延时队列实现。
2. RocketMq 延时队列
首先,RocketMq本身提供,几类的延时队列,
详细可以看源码
org.apache.rocketmq.store.config.MessageStoreConfig
private String messageDelayLevel = "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h";
定义了这么多的类型,那RocketMq是怎么操作的,TopicValidator在这个地方有定义了个,对应不同级别的延时队列,
org.apache.rocketmq.common.topic.TopicValidator
public static final String RMQ_SYS_SCHEDULE_TOPIC = "SCHEDULE_TOPIC_XXXX";
这个Topic就是存放不同延时级别的消息。
然后我们看一下,具体的流程
这个地方简单说一下,就是这个消息最终都是存放在CommitLog中,这个我贴个链接,
可以看一下,下面的文章
https://juejin.cn/post/6844903728521166856
大家感兴趣的可以看一下
方便大家理解,把入参可贴出来了,这个就是消息的基本信息
public class MessageExt extends Message {
private static final long serialVersionUID = 5720810158625748049L;
private String brokerName;
private int queueId;
private int storeSize;
private long queueOffset;
private int sysFlag;
private long bornTimestamp;
private SocketAddress bornHost;
private long storeTimestamp;
private SocketAddress storeHost;
private String msgId;
private long commitLogOffset;
private int bodyCRC;
private int reconsumeTimes;
public class MessageExtBrokerInner extends MessageExt {
private static final long serialVersionUID = 7256001576878700634L;
private String propertiesString;
private long tagsCode;
org.apache.rocketmq.store.CommitLog#putMessage
public PutMessageResult putMessage(final MessageExtBrokerInner msg) {
// Set the storage time
msg.setStoreTimestamp(System.currentTimeMillis());
// Set the message body BODY CRC (consider the most appropriate setting
// on the client)
msg.setBodyCRC(UtilAll.crc32(msg.getBody()));
// Back to Results
AppendMessageResult result = null;
StoreStatsService storeStatsService = this.defaultMessageStore.getStoreStatsService();
String topic = msg.getTopic();
int queueId = msg.getQueueId();
final int tranType = MessageSysFlag.getTransactionValue(msg.getSysFlag());
if (tranType == MessageSysFlag.TRANSACTION_NOT_TYPE
|| tranType == MessageSysFlag.TRANSACTION_COMMIT_TYPE) {
// Delay Delivery
**// 延时消息,**
if (msg.getDelayTimeLevel() > 0) {
if (msg.getDelayTimeLevel() > this.defaultMessageStore.getScheduleMessageService().getMaxDelayLevel()) {
msg.setDelayTimeLevel(this.defaultMessageStore.getScheduleMessageService().getMaxDelayLevel());
}
//主题
topic = TopicValidator.RMQ_SYS_SCHEDULE_TOPIC;
//计算放到哪个queue中
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()))