RocketMQ篇之-消息存储
目录
- RocketMQ篇之-消息存储
- (前置)消息存储交互流程
- (一)存储系统
- [1. 内存存储](#1. 内存存储)
- [2. 关系型数据库存储](#2. 关系型数据库存储)
- [3. 文件存储](#3. 文件存储)
- (二)消息的存储和发送
- [1. 消息存储(顺序写入)](#1. 消息存储(顺序写入))
- [2. 消息发送(零拷贝)](#2. 消息发送(零拷贝))
- (三)存储文件结构
- (四)刷盘机制
- [1. 同步刷盘](#1. 同步刷盘)
- [2. 异步刷盘](#2. 异步刷盘)
- 选择
- 总结
RocketMQ作为一款分布式消息中间件,高可靠性是其最重要的特性之一。
所以需要将消息进行持久化存储,以保证消息不丢失。
RocketMQ的消息存储是RocketMQ的核心组件之一,负责消息的存储和传输。RocketMQ的消息存储主要包括CommitLog、ConsumeQueue、IndexFile、Checkpoint等几个部分。
(前置)消息存储交互流程
- 生产者发送消息MQ;
- MQ将消息存到存储系统;
- 返回消息存储结果;
- 消费者从存储系统拉取消息,消费消息;
- 消费者消费成功,返回消费结果;
- 存储系统删除消息。
(一)存储系统
在上面的流程中,存储系统是RocketMQ的核心组件之一,负责消息的读写。
存储系统有以下几种选择:
- 内存存储等;
- 关系型数据库存储;
- 文件存储;
在RocketMQ中,使用的是文件存储。
1. 内存存储
内存存储是一种高性能的存储方式,但是内存存储的数据是不稳定的,一旦断电,数据就会丢失。即便是以Redis为代表的内存数据库,也无法保证数据的持久化,在持久化方面,还是选择文件存储。所以对消息来说,内存存储是不适合的。
2. 关系型数据库存储
关系型数据库存储是一种常见的存储方式,像MySQL、Oracle等都可以作为消息存储。阿帕奇的ActiveMQ、Pulsar等都是使用关系型数据库作为消息存储。但其实关系型数据库底层也是文件存储,所以对比直接使用文件存储,关系型数据库存储的性能会有所下降。
3. 文件存储
文件存储是一种常见的存储方式,像Kafka、RocketMQ、RabbitMQ等都是使用文件存储。文件存储的优点是性能高,稳定性好,适合消息存储。
(二)消息的存储和发送
1. 消息存储(顺序写入)
磁盘的读写速度虽然比内存慢,但是和网络IO相比,磁盘的读写速度还是很快的。现在的磁盘读写速度已经达到了几百MB/s甚至上千MB/s,所以对于消息存储来说,磁盘的读写速度是足够的。
但是在随机读写方面,磁盘的性能就会有比较严重的下降,所以RocketMQ的消息存储是顺序写入的,这样可以提高磁盘的读写性能。
2. 消息发送(零拷贝)
消息的发送,需要将磁盘内的数据发送到网络中,在这个过程中,会涉及到系统的内核态和用户态的切换,这个过程是比较耗时的。
把磁盘数据发送到网络中,需要经过以下几个步骤:
- 从磁盘中读取数据;
- 将读取的数据发送到网络中;
看似只有两个步骤,但是在实际的操作中,还会涉及到内核态和用户态的切换和数据复制等操作:
- 从磁盘中读取数据,磁盘复制 -> 内核态的缓冲区;
- 内核态的缓冲区复制 -> 用户态的缓冲区;
- 将数据发送到网络中,从用户态的缓冲区复制 -> 网络驱动的内核态缓冲区;
- 网络驱动的内核态缓冲区复制 -> 网络中;
重要‼️: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的消息持久化的方式,保证消息不会丢失。
我们讲了以下几部分相关的内容:
- 存储系统的选择,选择了文件存储。
- 消息的存储和发送,通过顺序写入和零拷保证性能。(也是RocketMQ为什么高性能的主要原因)
- 存储文件结构,CommitLog、ConsumeQueue和IndexFile。
- 刷盘机制,同步刷盘和异步刷盘。
这些内容是RocketMQ消息存储的核心内容,对于理解RocketMQ的消息存储机制非常重要。希望本文对你有所帮助,如果有任何问题,欢迎留言讨论。