2:初始存储偏移量所用的内存
this.byteBufferIndex.flip();
this.byteBufferIndex.limit(CQ_STORE_UNIT_SIZE);
this.byteBufferIndex.putLong(offset);
this.byteBufferIndex.putInt(size);
this.byteBufferIndex.putLong(tagsCode);
这里将消息的偏移量、大小、tagsCode等信息,都暂存到了一块ByteBuffer中。
3:获取此次存储消息偏移量所用的MappedFile
final long expectLogicOffset = cqOffset * CQ_STORE_UNIT_SIZE;
MappedFile mappedFile = this.mappedFileQueue.getLastMappedFile(expectLogicOffset);
前面我们讲到,ConsumeQueue本身也是采用MappedFileQueue用来存储偏移量的,这里便是获取MappedFileQueue中的最后一个MappedFile,用来存储消息。
ConsumeQueue 中用来存储消息偏移量的结构大小为 CQ_STORE_UNIT_SIZE,为20个字节,cqOffset为 ConsumeQueue 中已经记录了多少条消息的偏移量,所以 expectLogicOffset 即为当前需要存储的消息偏移量结构,在ConsumeQueue的MappedFileQueue中的位置。
4:更新maxPhysicOffset,并将暂存在ByteBuffer中的消息偏移信息,追加到MappedFile中。
this.maxPhysicOffset = offset;
return mappedFile.appendMessage(this.byteBufferIndex.array());
此时,消息偏移量就被成功存储到ConsumeQueue中了。
总结
通过上面的分析,我们知道了ConsumeQueue的作用及更新流程,总结来说,它就是用来记录消息在CommitLog中偏移量的,便于Consumer快速定位消息。
消息偏移量的更新分为下面几步:
1:ReputMessageService不断从CommitLog中查询是否有新存储的消息;
2:如果有新消息,便通过Dispatcher通知ConsumeQueue;
3:ConsumeQueue收到通知后会将消息偏移量存储到自身的MappedFile中。
此时回到我们的这里:
public void executeOnTimeup() {
ConsumeQueue cq =
ScheduleMessageService.this.defaultMessageStore.findConsumeQueue(TopicValidator.RMQ_SYS_SCHEDULE_TOPIC,
delayLevel2QueueId(delayLevel));
这个离上面非常远了。。中间隔了一个ConsumeQueue的学习。。
这里拿到ConsumeQueue,显然是准备搞消息的偏移了,看看下面干什么,让我来猜的话我觉得是发送消息的同时来更新ConsumeQueue的消费进度。