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

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

bf1d09811ba1159b423f00f0d3cbecab.png

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

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

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

消息发送存储流程

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

89236f5620e8a19214f6659b420a9a16.png

da743b9d47bc5181cea4b48bde6008bc.png

d2a60794ca9192c9a7c6084dce3e2cc1.png

核心步骤

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

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

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

  4. 将消息追加到commitLog中

  5. 释放锁

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

  7. 执行主从复制

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

e770a1454d5261ab08494814c748654d.png

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

存储文件组织与内存映射

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

e1c0c1850698a65d70cec82bdfb9b976.png

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

2ef5bd0c0ba9df410b5c86bd983ddde3.png

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

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

0ddb89ec8df196873b2a588077f699e2.png

内存映射

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

分页存储

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

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

如下图:

05c2c74d0ac30f0da3074afdc23ce51a.png

虚拟存储

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

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

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

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

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

IO原理

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

b64e4d2c0a6943ee6f3e1f47664f92a5.png

  1. 进程发起read系统调用

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

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

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

内存映射

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

4a9781226ee01d1d2840f66cf3fa983f.png

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

优势:

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

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

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

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

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值