RocketMQ高手之路系列之十三:RocketMQ存储设计到底强在哪?

简介: 对于一款消息中间件来说,优良的数据存储设计,是实现高性能消息吞吐以及消息查询的关键所在。因为消息中间件对于外部来说就是发消息消费消息的一个平台基础设施,但是从其本身来说,需要将海量消息数据信息持久化在RocketMQ节点所在的服务器上,这样即便是服务器断电,重启等情况下,也不至于丢失消息数据。另外在进行消息消费的时候,RocketMQ如何能借助自身的存储设计快速检索到对应的消息也是非常重要的,因此本文主要对RocketMQ存储设计进行了设计分析。

引言

对于一款消息中间件来说,优良的数据存储设计,是实现高性能消息吞吐以及消息查询的关键所在。因为消息中间件对于外部来说就是发消息消费消息的一个平台基础设施,但是从其本身来说,需要将海量消息数据信息持久化在RocketMQ节点所在的服务器上,这样即便是服务器断电,重启等情况下,也不至于丢失消息数据。另外在进行消息消费的时候,RocketMQ如何能借助自身的存储设计快速检索到对应的消息也是非常重要的,因此本文主要对RocketMQ存储设计进行了设计分析。

存储结构

RocketMQ对应的存储文件主要包括三类,分别是Commitlog文件、ConsumeQueue文件以及Index文件,每一个文件都有其特殊的使命。

image.png

Commitlog文件

当生产者将消息发送到RocketMQ的Broker之后,需要将消息进行持久化存储,防止消息数据丢失。RocketMQ将消息数据写入存储文件CommitLog中,按照消息的发送顺序写入文件当中,每个文件的大小约为1G,当达到文件大小限制后,就会创建新的CommitLog文件。RocketMQ作为消息中间件来说,最主要的数据流程就是基于主题的发布-订阅模式进行消息的发布以及消费,那么当消费者根据自己订阅的Topic进行消息消费的时候,Broker怎么在那么多的CommitLog文件中找到对应Topic的消息数据呢?

image.png

大家可以想一想,CommitLog文件中的消息数据是一条一条顺序写的,最笨的方法就是遍历文件,作为一款高性能的消息中间件,显然这不是一个好的解决方案。就像从数据库查询数据的时候,遍历的效率肯定是很低的。那么我们可不可以借助数据库提升数据查询的方式,使用索引来加快消息数据的查询呢?答案是肯定的。就像Mysql中的索引本身需要文件保存一样,在RocketMQ中页有单独保存索引的文件,就是

ConsumerQueue文件

在RocketMQ中,每个Topic对应多个MessageQueue,每个MessageQueue对应一组ConsumerQueue文件索引文件。ConsumerQueue文件中存储了消息相对于CommitLog文件的offset偏移量,CommitLog文件本身实际上也是通过偏移量来进行命名如第一个文件是0000000000000,那么第二文件就是消息总量之和00000001232321,往后新的文件再进行累计。为什么这么做呢?主要就是在进行消息查找的时候根据消息的偏移量通过二分查找快速定位具体的CommitLog文件,提升消息查找效率。需要说明的是,Broker在进行消息写入CommitLog文件中就会异步将其对应的偏移量写入ConsumerQueue文件中。

image.png

在ConsumerQueue文件中实际存储了CommitLog文件的offset偏移量、消息长度以及tag的hashcode,组成20字节的block块。其在Broker上面的存储路径大致是:…/store/consumequeue/{topic}/{queueid}/{file}。其中topic就是生产中订阅的主题,因此消费者在消费消息的时候,Broker会根据其对应的Topic找到对应的 ConsumerQueue文件,进而找到其索引位置,再到CommitLog文件中直接定位具体的消息。

Index文件

另外RocketMQ的特性功能就是可以实现按照消息的属性进行消息搜索,即建立了索引 Key 的 hashcode 与物理偏移量的映射关系,根据 key 先快速定义到 commitlog 文件。

image.png

存储性能设计精髓

上文中为大家阐述了RocketMQ关于存储结构的设计,优秀的存储设计师实现高性能读写的前提。那么除了存储结构的设计,RocketMQ也使用了一些性能优化手段来实现其强大的消息吞吐能力。

消息顺序写

前文中说过,消息进入RocketMQ之后,消息数据是通过顺序写的方式落到CommitLog文件中的。那么这里面就涉及两个问题,为什么进行顺序写以及是不是直接写磁盘文件。


1、为什么要顺序写?

当新的数据到来时,只要在之前的文件末尾进行数据追加就可以,这样的数据写入效率要比随机写入的效率高。


2、每次数据写入的时候是直接写磁盘文件吗?

我们可以反过想,如果每次都是落盘写入的话实际效率是不高的,无法满足消息中间件这种高吞吐的性能要求,因此RocketMQ实际是借助操作系统的page cache来提升写入效率的,消息并不是直接写入磁盘,认识先写入操作系统的page cache,然后再通过异步刷盘的方式,写入CommitLog文件中,这样借助顺序写以及系统的page cache可以时间近乎内存的数据写入效率。

同步刷盘和异步刷盘

刚才所说的异步写入,其实就是RocketMQ的异步刷盘模式,但是大家想想这个模式有没有什么问题。为了提升数据吞吐量,消息数据过来后,并没有直接写盘,而是在系统中的page cache中。那么此时如果Broker宕机了,那么此时的消息数据是容易丢失的。所以虽然异步刷盘的写入效率高但是也存在数据丢失的风险。


同步刷盘

在同步刷盘的场景下,当Broker接受到对应的消息之后,Broker将会把这条消息刷入磁盘的CommitLog中,才会返回确认消息给生产者。如果在进行消息写入的时候Broker挂了,那么生产者会感受到消息投递失败,一般都会都有消息重新发送的重试逻辑。

这样看消息似乎不会丢失了,但是由于每次都是先落盘,就会导致数据写入性能下降。


MMAP

在RocketMQ中使用了mmap技术来实现Conmmitlog文件的高性能读写,mmap就是一种内存映射文件的方法,对于传统的文件IO交互来说,需要经过多次的数据复制过程才能将用户进程的数据写入硬盘或者读入程序。而mmap可以直接将虚拟内存中的文件与硬盘中文件地址进行映射,减少了数据拷贝的过程,从而提升了数据写入的效率。关于这部分的内容可以参见以前的文章有详细的介绍。https://blog.csdn.net/Diamond_Tao/article/details/117969644

image.png

总结

本文主要堆RocketMQ的存储设计进行了分析,围绕如何实现高性能消息写入和查询展开了阐述,希望在分析这些优秀中间的具体实现过程中,我们可以将这些优秀设计融入到具体的项目实践中,当我们遇到类似的问题的时候可以借助于这些设计思想来解决实际的问题。

相关实践学习
消息队列RocketMQ版:基础消息收发功能体验
本实验场景介绍消息队列RocketMQ版的基础消息收发功能,涵盖实例创建、Topic、Group资源创建以及消息收发体验等基础功能模块。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
相关文章
|
6月前
|
消息中间件 存储 数据库
RocketMQ 流存储解析:面向流场景的关键特性与典型案例
RocketMQ 流存储解析:面向流场景的关键特性与典型案例
88600 9
|
6月前
|
存储 消息中间件 缓存
RocketMQ 5.0 分级存储背后技术优化包含那几个方面
RocketMQ 5.0 分级存储背后的技术优化是一个综合性的系统工程,需要考虑多个方面,包括存储介质的选择、数据读写策略的设计、数据压缩和解压缩技术的引入、自动的数据分级和迁移机制的实现,以及高可用性和容错性的保证等。这些技术优化的目的是为了实现存储成本和性能的最优平衡,提高系统的可靠性和可用性,满足大规模数据处理的需求。
179 1
|
6月前
|
消息中间件 存储 运维
|
3月前
|
消息中间件 存储 数据库
深入学习RocketMQ的底层存储设计原理
文章深入探讨了RocketMQ的底层存储设计原理,分析了其如何通过将数据和索引映射到内存、异步刷新磁盘以及消息内容的混合存储来实现高性能的读写操作,从而保证了RocketMQ作为一款低延迟消息队列的读写性能。
|
6月前
|
存储 消息中间件 对象存储
谈谈 RocketMQ 5.0 分级存储背后一些有挑战的技术优化
谈谈 RocketMQ 5.0 分级存储背后一些有挑战的技术优化
132728 246
|
6月前
|
消息中间件 存储 数据库
深度剖析 RocketMQ 5.0,流存储:流场景的诉求是什么?
本文将从使用的角度出发,来更详细的展示一下流存储的场景,看看它和业务消息的场景有哪些区别。 RocketMQ 5.0 面向流存储的场景,提供了哪些特性。再结合两个数据集成的案例,来帮助大家了解流存储的用法。
3505 2
|
6月前
|
存储 消息中间件 负载均衡
RocketMQ 5.0 分级存储背后的技术优化与挑战
RocketMQ 5.0 分级存储背后的技术优化与挑战
|
6月前
|
存储 消息中间件 Apache
谈谈 RocketMQ 5.0 分级存储背后一些有挑战的技术优化
谈谈 RocketMQ 5.0 分级存储背后一些有挑战的技术优化
|
11月前
|
消息中间件 存储 NoSQL
SpringBoot项目整合Redis,Rabbitmq发送、消费、存储邮件
SpringBoot项目整合Redis,Rabbitmq发送、消费、存储邮件
648 8
|
6月前
|
消息中间件 存储 Java
RocketMQ-初体验RocketMQ(06)-使用API操作RocketMQ ,理解RocketMQ的存储结构
RocketMQ-初体验RocketMQ(06)-使用API操作RocketMQ ,理解RocketMQ的存储结构
196 0