RocketMQ 笔记2 文件存储

MappedFileQueue  代表一类文件集合,比如consumequeue/{topic}/{queueId}/目录下的所有文件
MappedFile 代表一个文件,是对这个文件操作的封装
CommitLog 代表所有的commitLog文件,里面有一个MappedFileQueue的字段
ConsumeQueue 代表了topic+queueId的所有consumeQueue文件,里面也有一个MappedFileQueue


DefaultMessageStore存储操作类
private final CommitLog commitLog;

    private final ConcurrentMap<String/* topic */, ConcurrentMap<Integer/* queueId */, ConsumeQueue>> consumeQueueTable;


    private final FlushConsumeQueueService flushConsumeQueueService;//consumeQueue文件刷盘线程


    private final CleanCommitLogService cleanCommitLogService;//定时清理commitLog线程


    private final CleanConsumeQueueService cleanConsumeQueueService;//定时清理consumeQueue线程


    private final IndexService indexService;//索引文件


    private final AllocateMappedFileService allocateMappedFileService;


    private final ReputMessageService reputMessageService;//监控commitLog文件有变化写consumeQueue


    private final HAService haService;






 1.org.apache.rocketmq.store.DefaultMessageStore.load()  加载文件过程
 org.apache.rocketmq.store.MappedFileQueue.load()中加载目录下所有文件,设置position
 mappedFile.setWrotePosition(this.mappedFileSize);
 mappedFile.setFlushedPosition(this.mappedFileSize);
 mappedFile.setCommittedPosition(this.mappedFileSize);
 这样的话假如最后一个文件没有写满,停机,再启动好像不会接着写这个文件,会重新新建一个后续文件写消息








 2.org.apache.rocketmq.store.DefaultMessageStore.putMessage(MessageExtBrokerInner) 写消息过程->
 this.commitLog.putMessage(msg) 拿到最后一个mappedFile文件,可能需要新建文件,使用这个文件写入 ->


 org.apache.rocketmq.store.MappedFile.appendMessage(MessageExtBrokerInner, AppendMessageCallback)
 如果writeBuffer不为null,会先写到writeBuffer缓存里面,后续又线程定时commit写到fileChannel里面,写消息格式


org.apache.rocketmq.store.CommitLog.DefaultAppendMessageCallback.doAppend(long, ByteBuffer, int, MessageExtBrokerInner)


 写完后wrotePosition增加写的长度






 3.org.apache.rocketmq.store.CommitLog.handleDiskFlush(AppendMessageResult, PutMessageResult, MessageExt) 刷盘过程
 同步刷盘:
 向GroupCommitService提交一个GroupCommitRequest,同时阻塞线程,等待刷盘结果
 GroupCommitService的doCommit方法,在刷盘(CommitLog.this.mappedFileQueue.flush(0))结束后唤醒上面的线程,返回最终结果


 异步刷盘:
 唤醒FlushRealTimeService,定时调用mappedFileQueue.flush刷盘






 4.consumeQueue文件的写入
 org.apache.rocketmq.store.DefaultMessageStore.ReputMessageService 启动后监控commitLog文件MaxOffset有无变化,
 当有变化时候
 SelectMappedBufferResult result = DefaultMessageStore.this.commitLog.getData(reputFromOffset) 拿到新消息,设置新的MaxOffset


 从ByteBuffer中读取消息内容,构建DispatchRequest,包含topic,topic,commitLogOffset,msgSize,tagsCode,有了这些就可以写consumeQueue文件了
 DispatchRequest dispatchRequest =
    DefaultMessageStore.this.commitLog.checkMessageAndReturnSize(result.getByteBuffer(), false, false);




调用DefaultMessageStore.this.doDispatch(dispatchRequest)
CommitLogDispatcherBuildConsumeQueue  写consumeQueue文件
CommitLogDispatcherBuildIndex 写index文件






5.文件结构
CommitLog
每个文件的大小默认为1G,commitlog的文件名fileName,名字长度为20位,左边补0,剩余为起始偏移量,比如 00000000000000000000 代表了第一个文件,起始偏移量为 0, 文件大小为 1G=1073741824; 当这个文件满了,第二个文件名字为 00000000001073741824


Consumequeue
消息起始物理偏移量(physical offset, long 8字节)+消息大小(int,4字节)+tagsCode(long 8字节) 
每个 cosumequeue 文件的名称 fileName,名字长度为 20 位,左边补零,剩余为起始偏量; 比如 00000000000000000000 代表了第一个文件,起始偏移量为 0,文件大小为 600W, 当第一个文件满之后创建的第二个文件的名字为00000000000006000000,起始偏移量为6000000,以此类推,第三个文件名字为00000000000012000000,起始偏移量12000000。消息存储的时候会顺序写入文件,当文件满了,写入下一个文件。






6.broker读消息过程
org.apache.rocketmq.broker.processor.PullMessageProcessor.processRequest(Channel, RemotingCommand, boolean) 收到拉取消息请求


org.apache.rocketmq.store.DefaultMessageStore.getMessage(String, String, int, long, int, MessageFilter) 使用DefaultMessageStore读消息


ConsumeQueue consumeQueue = findConsumeQueue(topic, queueId) 找到对应consumeQueue


SelectMappedBufferResult bufferConsumeQueue = consumeQueue.getIndexBuffer(offset) 读取指定偏移处的ConsumeQueue内容


long offsetPy = bufferConsumeQueue.getByteBuffer().getLong();
int sizePy = bufferConsumeQueue.getByteBuffer().getInt();
long tagsCode = bufferConsumeQueue.getByteBuffer().getLong();  得到消息偏移地址,大小,tagsCode


SelectMappedBufferResult selectResult = this.commitLog.getMessage(offsetPy, sizePy); 使用commitLog读取消息内容




                            

猜你喜欢

转载自blog.csdn.net/u013038630/article/details/80327183