rocketmq消息存储原理_RocketMQ消息的存储

RocketMQ主要存储文件包括,commitLog、consumeQueue、indexFile,所有主题消息都顺序存储在一个文件中,以确保消息的顺序写;同时,RocketMQ又引入了consumeQueue,每个主题包含多个消费队列,每个消费对了对应一个文件,如下图:

rocketmq消息存储原理_RocketMQ消息的存储_第1张图片

  1. CommitLog:消息存储文件,所有消息主题的消息都存储在CommitLog文件中。

  2. ConsumeQueue消息消费队列,消息到达CommitLog文件后,将异步转发到消息消费队列,供消息消费者消费。

   3.   IndexFile索引文件,为了快速检索CommitLog中的数据。

消息发送存储流程

入口是DefaultMessageStore的的putMessage方法,如图:

rocketmq消息存储原理_RocketMQ消息的存储_第2张图片

rocketmq消息存储原理_RocketMQ消息的存储_第3张图片

rocketmq消息存储原理_RocketMQ消息的存储_第4张图片

核心步骤

  1. 获取当前可以写入的commitLog文件

  2. 获取锁(这里可以看出commitLog的写入是串行的)

  3. 判断是否需要创建commitLog文件

  4. 将消息追加到commitLog中

  5. 释放锁

  6. 将内存数据持久化到磁盘

  7. 执行主从复制

跟踪putMessage方法过程中,会进入CommitLog的doAppend方法,如图:

rocketmq消息存储原理_RocketMQ消息的存储_第5张图片

类CommitLog记录了每个消息队列最后写入的消息偏移量,此时了找到此消息应该存储的磁盘位置,然后将消息存储到byteBuffer中(此时并未持久化到磁盘)

存储文件组织与内存映射

RocketMQ通过内存映射来提高IO性能,无论是commitLog、indexFile还是consumeQueue都被设计成固定大小,一个写满了就再创建另一个,另一个的文件名是第一条消息的全局物理偏移量,如图:

rocketmq消息存储原理_RocketMQ消息的存储_第6张图片

在代码里使用MappedFile和MappedFileQueue来组织文件,对应关系如下图:

rocketmq消息存储原理_RocketMQ消息的存储_第7张图片

MappedFile是RocketMQ内存映射文件的具体实现

其中MappedByteBuffer来是java的nio包,使用内存映射,节省了数据在用户空间到内核空间的来回copy,大大的提高了IO性能

rocketmq消息存储原理_RocketMQ消息的存储_第8张图片

内存映射

先来了解一下分页存储和虚拟存储:

分页存储

操作系统在运行程序时,需要为每一个进程分配内存。比如A进程需要200M,B进程需要300M,c进程需要100M。那么操作系统应该如何为他们分配这些内存呢?

这里将程序的地址空间分为多个页,把物理空间也分为和页一样大小的物理块,为了保证进程能够正确运行,即能够在内存中找到每个页面所对应的物理块,系统为每一个进程建立了一张页面映像表,简称页表。在进程地址空间内的所有页,依次在页表中有一页表项,其中记录了相应页在内存中的物理块号。

如下图:

rocketmq消息存储原理_RocketMQ消息的存储_第9张图片

虚拟存储

我们玩的游戏比如Dota2,大小有150G左右,但我们电脑的内存也就8或G者12G,那么电脑是咋运行的游戏呢?答案就是虚拟存储;

所有现代操作系统都使用虚拟内存。虚拟内存意为使用虚假(或虚拟)地址取代物理(硬件RAM)内存地址。这样做好处颇多,总结起来可分为两大类:

  1. 一个以上的虚拟地址可指向同一个物理内存地址。

  2. 虚拟内存空间可大于实际可用的硬件内存。

应用程序在运行之前没必要全部装入内存,只要一部分就行,其余的部分留在磁盘上,如果程序需要访问的页面没有载入内存,就会产生缺页中断,此时操作系统就会将该页调入内存(swap),以便程序继续运行;

IO原理

有了上面的介绍我们再来看一下操作系统中的IO过程,如图:

b64e4d2c0a6943ee6f3e1f47664f92a5.png

  1. 进程发起read系统调用

  2. 内核随机向磁盘控制器发出信号,要求进行IO操作

  3. DMA将磁盘数据读取到内核缓冲区

  4. 内核缓冲区将数据拷贝到用户空间缓冲区

内存映射

上面我们看到操作系统的IO需要将数据在内核空间和用户空间进行拷贝,而内存映射文件则省去了该步骤,利用上面说的虚拟存储技术,可以用多个虚拟地址指向同一块物理地址,如下图:

rocketmq消息存储原理_RocketMQ消息的存储_第10张图片

这样一来,DMA就可以填充对内核空间和用户空间都可见的内存缓冲区了;

优势:

1.再也不需要read和write系统调用了

2.省去了数据从内核空间到用户空间的拷贝

3.用户如果修改了映射的内存空间数据,数据会被标记为脏页,自动刷新到磁盘

RocketMQ正是使用了内存映射代替传统的IO过程,来提高IO性能;

你可能感兴趣的:(rocketmq消息存储原理)