文章目录
版本
- 基于
rocketmq-all-4.3.1
版本
简介
-
RocketMQ消息存储是首先将消息追加到内存中,然后根据刷盘策略在不同时间刷盘。
- 同步刷盘,消息追加到内存,调用**MappedByteBuffer.force()**方法实现刷盘
- 异步刷盘,消息追加到内存后,立即返回给Producer。使用单独的异步线程按照一定的频率执行刷盘操作
-
Index文件的刷盘并不是采取定时刷盘机制,而是每更新一次Index文件就会将上一次的改动写入磁盘
-
刷盘代码CommitLog#handleDiskFlush,可以看到同步刷盘由GroupCommitService完成
public void handleDiskFlush(AppendMessageResult result, PutMessageResult putMessageResult, MessageExt messageExt) { //刷盘策略,同步刷盘阻塞等待,异步刷盘唤醒commitLogService // Synchronization flush if (FlushDiskType.SYNC_FLUSH == this.defaultMessageStore.getMessageStoreConfig().getFlushDiskType()) { final GroupCommitService service = (GroupCommitService) this.flushCommitLogService; if (messageExt.isWaitStoreMsgOK()) { //构建刷盘请求放入GroupCommitService队列中(List中) GroupCommitRequest request = new GroupCommitRequest(result.getWroteOffset() + result.getWroteBytes()); service.putRequest(request); //GroupCommitService线程在broker启动时会启动,阻塞,等待线程刷盘完成,默认超时时间5s,如果超时返回false //即如果超时,响应给生产者的是FLUSH_DISK_TIMEOUT boolean flushOK = request.waitForFlush(this.defaultMessageStore.getMessageStoreConfig().getSyncFlushTimeout()); if (!flushOK) { log.error("do groupcommit, wait for flush failed, topic: " + messageExt.getTopic() + " tags: " + messageExt.getTags() + " client address: " + messageExt.getBornHostString()); putMessageResult.setPutMessageStatus(PutMessageStatus.FLUSH_DISK_TIMEOUT); } } else { service.wakeup(); } } // Asynchronous flush else { if (!this.defaultMessageStore.getMessageStoreConfig().isTransientStorePoolEnable()) { //使用MappedByteBuffer,默认策略 flushCommitLogService.wakeup()