【RocketMQ 消息中间件】RocketMQ篇之-消息存储 为什么性能高 CommitLog ConsumeQueue IndexFile 刷盘机制 同步 异步

RocketMQ篇之-消息存储

目录

RocketMQ作为一款分布式消息中间件,高可靠性是其最重要的特性之一。

所以需要将消息进行持久化存储,以保证消息不丢失。

RocketMQ的消息存储是RocketMQ的核心组件之一,负责消息的存储和传输。RocketMQ的消息存储主要包括CommitLog、ConsumeQueue、IndexFile、Checkpoint等几个部分。

(前置)消息存储交互流程

  1. 生产者发送消息MQ;
  2. MQ将消息存到存储系统;
  3. 返回消息存储结果;
  4. 消费者从存储系统拉取消息,消费消息;
  5. 消费者消费成功,返回消费结果;
  6. 存储系统删除消息。

(一)存储系统

在上面的流程中,存储系统是RocketMQ的核心组件之一,负责消息的读写。

存储系统有以下几种选择:

  1. 内存存储等;
  2. 关系型数据库存储;
  3. 文件存储;

在RocketMQ中,使用的是文件存储。

1. 内存存储

内存存储是一种高性能的存储方式,但是内存存储的数据是不稳定的,一旦断电,数据就会丢失。即便是以Redis为代表的内存数据库,也无法保证数据的持久化,在持久化方面,还是选择文件存储。所以对消息来说,内存存储是不适合的。

2. 关系型数据库存储

关系型数据库存储是一种常见的存储方式,像MySQL、Oracle等都可以作为消息存储。阿帕奇的ActiveMQ、Pulsar等都是使用关系型数据库作为消息存储。但其实关系型数据库底层也是文件存储,所以对比直接使用文件存储,关系型数据库存储的性能会有所下降。

3. 文件存储

文件存储是一种常见的存储方式,像Kafka、RocketMQ、RabbitMQ等都是使用文件存储。文件存储的优点是性能高,稳定性好,适合消息存储。

(二)消息的存储和发送

1. 消息存储(顺序写入)

磁盘的读写速度虽然比内存慢,但是和网络IO相比,磁盘的读写速度还是很快的。现在的磁盘读写速度已经达到了几百MB/s甚至上千MB/s,所以对于消息存储来说,磁盘的读写速度是足够的。

但是在随机读写方面,磁盘的性能就会有比较严重的下降,所以RocketMQ的消息存储是顺序写入的,这样可以提高磁盘的读写性能。

2. 消息发送(零拷贝)

消息的发送,需要将磁盘内的数据发送到网络中,在这个过程中,会涉及到系统的内核态和用户态的切换,这个过程是比较耗时的。

把磁盘数据发送到网络中,需要经过以下几个步骤:

  1. 从磁盘中读取数据;
  2. 将读取的数据发送到网络中;

看似只有两个步骤,但是在实际的操作中,还会涉及到内核态和用户态的切换和数据复制等操作:

  1. 从磁盘中读取数据,磁盘复制 -> 内核态的缓冲区;
  2. 内核态的缓冲区复制 -> 用户态的缓冲区;
  3. 将数据发送到网络中,从用户态的缓冲区复制 -> 网络驱动的内核态缓冲区;
  4. 网络驱动的内核态缓冲区复制 -> 网络中;

重要‼️:RocketMQ通过mmap的方式将磁盘文件映射到内存中,这样可以减少内核态和用户态的切换,减少数据的复制,提高性能,也就是所谓的零拷贝。

(三)存储文件结构

在RocketMQ中,有三个重要的文件类型:commitlog、consumequeue和index文件。它们分别有不同的用途和存储内容。

1. CommitLog

用途:

CommitLog文件是RocketMQ存储消息的核心文件。所有的消息首先都会被写入到CommitLog文件中。

它以顺序写的方式保存消息,以确保写入的高性能和可靠性。

存储内容:

CommitLog文件存储的是消息的完整内容,包括消息的元数据(如消息ID、主题、队列ID等)和消息体。

联系:

所有消息最初都会写入到CommitLog文件中,然后再由消息服务组件(例如:ConsumeQueue和IndexFile)进行进一步的处理。

2. ConsumeQueue

用途:

ConsumeQueue是RocketMQ的消费者队列文件,主要用于提高消息消费的效率。

它相当于消息的索引文件,消费者可以通过ConsumeQueue快速定位到需要消费的消息在CommitLog中的位置。

存储内容:

ConsumeQueue文件存储的是消息在CommitLog中的物理偏移量、消息大小和消息的标签哈希值。

联系和区别:

ConsumeQueue是从CommitLog文件中生成的,用于加速消息消费。它只存储消息的索引信息,而不是消息的完整内容

3. IndexFile

用途:

IndexFile是RocketMQ的索引文件,主要用于通过消息的索引(例如:消息的唯一标识符Key)快速查找消息。

它实现了基于哈希的索引机制,支持消息的快速检索。

存储内容:

IndexFile文件存储的是消息的Key(唯一标识符)、消息的物理偏移量和消息的存储时间。

联系和区别:

IndexFile也是从CommitLog文件中生成的,但它的目的是为了提供消息的快速检索功能。

与ConsumeQueue不同,IndexFile是通过消息的Key来查找消息,而不是通过主题和队列。ConsumeQueue是通过消息的主题和队列ID来查找消息。

总结

CommitLog:RocketMQ中存储所有消息的核心文件,保存消息的完整内容。

ConsumeQueue:消费者队列文件,用于加速消息消费,存储消息的索引信息。

IndexFile:索引文件,用于快速检索消息,存储消息的Key和物理偏移量。

这三种文件共同协作,确保了RocketMQ的高性能和高可靠性。CommitLog负责消息的存储,ConsumeQueue提高了消息的消费效率,而IndexFile则提供了消息的快速检索能力。

(四)刷盘机制

RocketMQ的消息存在磁盘中,这样能保证在断电后消息不会丢失。

在消息写入磁盘的过程中,有两种刷盘机制:同步刷盘和异步刷盘。

1. 同步刷盘

同步刷盘是指在消息写入磁盘后,需要等待磁盘的写入操作完成后,才返回写入成功的结果。

同步刷盘的优点是数据安全,可以保证消息不会丢失。但是同步刷盘的缺点是性能较差,因为需要等待磁盘的写入操作完成后才能返回结果。

2. 异步刷盘

异步刷盘是指在消息写入磁盘后,不需要等待磁盘的写入操作完成,可以立即返回写入成功的结果,然后由后台线程负责将数据刷盘到磁盘中。

异步刷盘的优点是性能较好,因为不需要等待磁盘的写入操作完成,可以立即返回结果。但是异步刷盘的缺点是数据不安全,可能会丢失部分消息。

选择

在实际的应用中,可以根据业务的需求选择合适的刷盘机制。如果对数据的安全性要求较高,可以选择同步刷盘;如果对性能要求较高,可以选择异步刷盘。

总结

RocketMQ的消息存储是RocketMQ的消息持久化的方式,保证消息不会丢失。

我们讲了以下几部分相关的内容:

  1. 存储系统的选择,选择了文件存储。
  2. 消息的存储和发送,通过顺序写入和零拷保证性能。(也是RocketMQ为什么高性能的主要原因)
  3. 存储文件结构,CommitLog、ConsumeQueue和IndexFile。
  4. 刷盘机制,同步刷盘和异步刷盘。

这些内容是RocketMQ消息存储的核心内容,对于理解RocketMQ的消息存储机制非常重要。希望本文对你有所帮助,如果有任何问题,欢迎留言讨论。

相关推荐
SunnyRivers8 天前
LangChain中间件详解
中间件·langchain
金刚猿8 天前
06_虚拟机中间件部署_xxl-job 部署
中间件·xxl-job·xxl-job-admin
Loo国昌9 天前
【AI应用开发实战】Guardrail风险控制中间件:Agent系统的安全防线
人工智能·python·安全·自然语言处理·中间件·prompt
键盘鼓手苏苏9 天前
Flutter for OpenHarmony: Flutter 三方库 ntp 精准同步鸿蒙设备系统时间(分布式协同授时利器)
android·分布式·算法·flutter·华为·中间件·harmonyos
Coder_Boy_10 天前
Java后端核心技术体系全解析(个人总结)
java·开发语言·spring boot·分布式·spring cloud·中间件
CN-David10 天前
CentOS搭建Mycat中间件
linux·mysql·中间件·centos·mariadb
三水不滴11 天前
消息队列消费性能优化:批量消费 + 手动 ACK 提升吞吐量
经验分享·笔记·中间件·性能优化
nix.gnehc11 天前
Go进阶攻坚+专家深耕级学习清单|聚焦高并发、高性能中间件/底层框架开发(Java开发者专属)
学习·中间件·golang
金刚猿12 天前
05_虚拟机中间件部署_ubuntu 系统 安装 Redis 7.0.15
redis·ubuntu·中间件
GEM的左耳返12 天前
Java面试深度剖析:从JVM到云原生的技术演进
jvm·spring boot·云原生·中间件·java面试·分布式架构·ai技术