RocketMQ消息存储(一) - mmap零拷贝

RocketMQ消息存储(一) - mmap零拷贝(前置篇)

从本篇开始研究Broker 对文件的存储, 这些文件分为三类 (CommitLog , ConsumeQueue , IndexFile) 。

而在分析文件存储的源码之前, 我们要先了解一个重要的前置知识: 零拷贝IO 技术.

下面是针对不同的开源MQ总结的底层使用的IO方式:

MQ read/write
RocketMQ mmap/mmap (默认,可通过修改配置,配置成FileChannel,原因是作者想避免PageCache的锁竞争,通过两层架构实现读写分离)
Kafka record记录基于sendfile/sendfile index基于mmap/mmap
ActiveMQ RandomAccessFile/RandomAccessFile

1. 基本概念

我们需要先弄清楚, 物理内存与虚拟内存之间的关系, 以及虚拟内存下 用户空间与内核空间的关系, 弄清楚这些概念后对我们去理解 零拷贝 就非常的简单。

下面时我从 网上荡下来的一张图片:

这个图片我认为 非常清晰的能够体现出 上述我说的关系。

  • 物理内存: 就是实际上计算机真实的内存大小。

  • 虚拟内存:为了解决多进程出现同时操作同一物理内存地址的现象,于是就抽象虚拟内存。

  • 用户空间/内核空间: 为了系统安全性考虑,用户进程不能直接操作底层内核,因此就把 虚拟内存 又划分出了 用户空间 、内核空间两部分。

  • 映射:

    img

    上面这一张图是 虚拟内存 映射到 物理内存。

    多进程的虚拟内存中的内核空间是共享的,都映射在物理内存的系统内核空间上。 而虚拟内存中的用户空间 则被映射到了不同的物理内存区域。

2. mmap内存映射原理分析

以上我们清楚了 物理内存与虚拟内存之间的映射关系, 它们之间实际上是通过 页表和MMU的方式来实现 地址之间的转换映射。

而本小节所说的 mmap内存映射 中的 映射 主要指的是 硬盘上文件的位置 与 **虚拟内存地址空间 **的 一 一对应,这种关系是逻辑上的概念。

注意: 在mmap的内存映射过程中, 并没有实际的数据拷贝,文件也并没有载入物理内存,只是逻辑上与虚拟内存形成了映射关系。

img

过程1: 实际上就是mmap内存映射, 只是建立了 文件 与 虚拟内存之间 逻辑上的映射关系。

假设 这时候 需要 读取文件上的一段数据, 因为 虚拟内存 与 文件的位置 已经建立了逻辑上的映射关系, 一次直接通过 虚拟内存来从物理内存上获取数据。

过程2:通过虚拟内存地址与物理内存地址的转换, 能够访问到 目标那块地址 上有无数据。 若没有数据,则说明文件没有加载到物理内存中,因此会产生缺页中断。

过程3:产生了缺页中断,因此就需要物理内存的内核去完成数据拷贝。 也就是将文件的数据 加载到 对应的物理内存地址中。

过程4:若在加载数据到物理内存的过程中, 物理内存的空间不够用, 因此就会产生 swap 交换, 从物理内存上腾出一部分空间给文件数据使用。

posted @ 2022-03-09 16:39  s686编程传  阅读(449)  评论(0编辑  收藏  举报