RocketMQ消息存储之物理存储与逻辑存储

RocketMQ源码深度解析一之消息存储 前言:RocketMQ的消息持久化是基于文件系统,而从效率来看文件系统>kv存储>关系型数据库。那么,到底是如何存储的,相信对源码进行解析,将会是我们大大提高对消息存储的认识。 阅读详情

目录

一、几种常用的消息存储类型比较

二、RocketMQ存储文件的组成部分

三、物理存储之CommitLog

1、CommitLog目录结构

2、CommitLog的存储结构 

四、逻辑存储之ConsumeQueue和Index

1、ConsumeQueue

2、Index

1)IndexHead 数据 

2)Hash槽

3)Index 条目列表

五、总结


        RocketMQ消息存储主要发生在Broker端,作为一种高可用消息中间件,RocketMQ具有独特的消息存储方式:RocketMQ消息存储分为物理存储和逻辑存储,物理存储发生在CommitLog文件中;逻辑存储发生在ConsumeQueue和Index文件中。

一、几种常用的消息存储类型比较

        下表对比下业界常用的存储类型:

存储类型

常见的几款MQ产品

存储方式

存储效率排名

易于实现与快速集成排名

文件系统

RocketMQ、Kafka、RabbitMQ

消息刷盘(同步刷盘、异步刷盘)

1

3

关系型数据库DB

ActiveMQ

默认采用KahaDB做消息存储,可选JDBC方式做消息持久化

3

1

分布式KV存储

ZeroMQ

依赖levelDB、RocksDB和Redis等作为消息持久化存储

2

2

        从上述表格可以看出从存储效率方面来看,文件系统存储类型胜出,而文件系统通常有异步和同步刷盘两种方式。对于消息中间件来说,本身应该尽量减少对于外部第三方中间件的依赖,因为相对于应用来说,消息中间件本身就是一种依赖,如果消息中间件又有第三方依赖,可能会导致设计过于复杂,因此采用文件系统在这方面还是有比较大的优势的。

二、RocketMQ存储文件的组成部分

        RocketMQ文件存储在store文件夹里,里面包含了commitlog、config、consumequeue、index这4个文件夹和abort、checkpoint两个文件。store文件夹下的具体目录参考下面目录树:

RocketMQ
      |--store
             |-commitlog
             |     |-00000000000000000000
             |     |-00000000001073741824
             |-config
             |     |-consumerFilter.json
             |     |-consumerOffset.json
             |     |-delayOffset.json
             |     |-subscriptionGroup.json
             |     |-topics.json
             |-consumequeue
             |     |-SCHEDULE_TOPIX_XXX
             |     |-topicA
             |     |-topicB
             |            |-0
             |            |-1
             |            |-2
             |            |-3
             |                  |-00000000000000000000
             |                  |-00000000001073741824
             |-index
             |     |-00000000000000000000
             |     |-00000000001073741824
             |-abort
             |-checkpoint

        下文主要介绍 CommitLog、ConsumeQueue和Index。

三、物理存储之CommitLog

        在RocketMQ中CommitLog的作用是存储所有topic的消息,CommitLog的存储文件地址是$HOME\store\commitlog\${fileName},每个文件默认大小是1GB,当超过1GB时,会自动创建一个新的CommitLog文件进行存储。

1、CommitLog的目录结构

        CommitLog的文件名长度为20位,左边补齐零,最右边为偏移量。例如:文件名00000000000000000000代表了第一个文件,起始偏移量为0,文件大小为1G=1073741824;假设第一个文件存满了,则会生成第二个文件00000000001073741824,起始偏移量为1073741824,依次类推。

图1  CommitLog的目录结构

        CommitLog每条消息存储长度不同,其逻辑视图可以参考下图,每条消息的前4个字节存储该消息的总长度。

图2 CommitLog的逻辑视图

2、CommitLog的存储结构 

        CommitLog的存储结构如下:

图3 CommitLog的存储结构

编号

字段简称

字段长度(字节)

含义

1

msgLen

4

消息的长度,消息的长度是整个消息体所占用的字节数的大小

2

magicCode

4

魔数,是固定值,MAGICCODE = 0xdaa320a7

3

bodyCRC

4

消息体的CRC,用于防止网络、硬件等故障导致数据与发送时不一致带来的问题,当broker重启recover时会校验

4

queueId

4

队列id,表示消息发到了哪个consumequeue

5

flag

4

网络通信层标记。创建Message对象时由生产者通过构造器设定的flag值,可以用于标记是请求,还是响应亦或是oneway(producer发只管发出消息不管返回值)类型,在RemotingCommand有用到

6

queueOffset

8

在consumequeue中的偏移量

7

physicalPosition

8

代表消息在commitLog中的物理起始地址偏移量

8

sysFlag

4

指明消息是事务状态等消息特征,可参考MessageSysFlag类。二进制为四个字节从右往左数:

  1. 当第1个字节为1(值为1)时表示表示消息是压缩的(Compressed);

  2. 当第2个字节为1(值为2)表示多消息(MultiTags);

  3. 当4个字节均为0(值为0)时表示非事务消息;

  4. 当第3个字节为1(值为4)时表示prepared消息;

  5. 当第4个字节为1(值为8)时表示commit消息;

  6. 当第3/4个字节均为1时(值为12)时表示rollback消息。

9

msg born timestamp

8

producer发送消息的时间戳

10

msg host

8

producer的host(address:port)

11

store timestamp

8

消息存储的时间戳

12

store host

8

broker的host(address:port)

13

reconsume time

4

消息被某个订阅组重新消费了几次(订阅组之间独立计数),因为重试消息发送到了topic名字为%retry%groupName的队列queueId=0的队列中去了,成功消费一次记录为0;

14

prepare transaction offset

8

表示是prepared状态的事务消息偏移量,RocketMQ事务消息基于两阶段提交

15

body length

4

消息体长度

16

msg body

bodyLength

消息体的内容

17

topic length

1

topic的长度,topc的长度最多不能超过127个字节,超过的话存储会出错(有前置校验)

18

topic

topicLength

topic的内容值

19

properties Length

2

属性值大小

20

properties

propertiesLength

RocketMQ内部用到的一些属性。例如发送消息的TAG就存放在Properties里面,Properties中的一些常用key都定义在了MessageConst里面

四、逻辑存储之ConsumeQueue和Index

        RocketMQ的消息存储采用的是混合型的存储结构,所谓混合型存储结构,就是Broker单个实例下所有的队列共用一个CommitLog来存储,这样会导致查询的时候无法快速定位具体的某个消息。于是就有了ConsumeQueue和Index两个逻辑存储文件。

        RocketMQ的消息存储架构可以参考下图。

图4 RocketMQ的消息存储架构

        从上图可以看出,Producer生产任意的消息后,无论Topic是否相同,都会将消息内容存储到CommitLog中,当CommitLog存储满了,则会创建一个新的CommitLog文件继续存储新生成的消息。此外,在Broker端,会有一个后台服务线程——ReputMessageService会不停地分发请求并异步构建ConsumeQueue(逻辑消费队列)和IndexFile(索引文件)。而Consumer端可以根据ConsumeQueue中的数据查找具体的消息。IndexFile则为消息查询提供了一种通过key或时间区间来查询消息的方法。下面主要介绍下ConsumeQueue和IndexFile。 

1、ConsumeQueue

        RocketMQ基于主题订阅模式实现消息的消费,但是在CommitLog中存储的消息是不连续的,如果从CommitLog检索该消息文件会很慢,为了提高效率,对应的主题的队列建立了索引文件,为了加快消息的检索和节省磁盘空间,每一个ConsumeQueue条目存储了消息的关键信息CommitLog文件中的偏移量、消息长度、tag的hashcode值。下图展示消息到ConsumeQueue的原理。

图5 消息到ConsumeQueue及从ConsumeQueue消费的示意图

        一个ConsumeQueue表示一个topic的一个queue,类似于kafka的一个partition,单个ConsumeQueue文件中默认包含30万个条目,ConsumeQueue文件名采取定长设计,每一个条目共20个字节,分别为8字节的CommitLog物理偏移量、4字节的消息长度、8字节tag hashcode,单个文件由30W个条目组成,可以像数组一样随机访问每一个条目,每个ConsumeQueue文件大小约5.72M。

        ConsumeQueue可以看成是基于topic的CommitLog索引文件,故ConsumeQueue文件夹的组织方式如下:topic/queue/file三层组织结构,具体存储路径为:$HOME/store/consumequeue/{topic}/{queueId}/{fileName},ConsumeQueue具体目录结构如下所示:

图6  ConsumeQueue目录结构

        上述的TopicTest是topic名,TopicTest下有4个文件夹,分别代表不同的queueId。每个queueId下存储具体的ConsumeQueue文件,如上图的00000000000000000000文件。消费者在读取消息时,先读取ConsumeQueue,再通过ConsumeQueue中的位置信息读取CommitLog,得到原始的消息。

2、Index

        IndexFile(索引文件)用于为生成的索引文件提供访问服务。Index文件的存储位置是:$HOME \store\index\${fileName},它通过MsgId或消息Key值查询消息真正的实体内容。在实际的物理存储上,文件名则是以创建时的时间戳命名的,固定的单个IndexFile文件大小约为420M,一个IndexFile可以保存 2000W个索引。IndexFile的文件结构如下所示:

图7 IndexFile文件结构

1)IndexHead 数据 

        IndexHead包含了6个部分:

  1. beginTimestamp:该IndexFile包含消息的第一条消息的存储时间。大小为8字节。
  2. endTimestamp:该IndexFile包含消息的最后一条消息的存储时间。大小为8字节。
  3. beginPhyoffset:第一条消息在commitlog的偏移量。大小为8字节。
  4. endPhyoffset:最后一条消息在commitlog的偏移量。大小为8字节。
  5. hashSlotCount:已经填充的slot数。大小为4字节。
  6. indexCount:该IndexFile包含的索引个数。大小为4字节。

2)Hash槽

        Hash槽的作用就是存放当前slot下最新index的序号。每当放一个新的消息的index进来,首先取MessageKey的hashCode,然后用hashCode对slot总数取模,得到应该放到哪个slot中,slot总数默认500W个。只要是取hash就必然面临hash冲突的问题,跟HashMap一样,IndexFile也是使用一个链表结构来解决hash冲突。只是这里跟HashMap稍微有点区别的地方是,slot中放的是最新index的指针。这是因为一般查询的时候肯定是优先查最近的消息。

 

图8 IndexFile存储示意图 

        从上图可以看出,IndexFile结构与hash表很相似,固定数量的slot组成数组,每个slot对应一条index链,index之间通过链表方式组织在一起。slot的值对应当前slot下最新的那个index的序号,而index中存储了当前slot下以及当前index的前一个index序号,这样就把slot下的所有index链起来了。

3)Index 条目列表

        每个Index条目固定长度为20字节,存放真正的索引数据。Index总共大概有2000W,也就是说平均每个slot存4个Index。Index组成结构包含下列几种:

  1. hashcode:消息key的hashcode。
  2. phyoffset:消息对应的物理偏移量。
  3. timedif:该消息存储时间与第一条消息的时间戳的差值,小于0表示该消息无效。
  4. preIndexNo:该条目的前一条记录的 Index 索引,hash冲突时,根据该值构建链表结构。

五、总结

        本文主要介绍RocketMQ的消息存储,RocketMQ消息分为物理存储(CommitLog)和逻辑存储(ConsumeQueue及Index),最开始介绍了业界常用的消息存储类型,并对这些消息存储方式进行了对比。接下来分别介绍CommitLog、ConsumeQueue及Index。通过本文可以了解到RocketMQ在消息存储设计方面的巧妙性:通过物理存储提高Producer端发送消息的速度;通过ConsumeQueue提高Consumer端消费消息的速度;Index文件提供了一种根据key或者时间来查询具体消息的渠道。

RocketMQ原理剖析 RocketMQ架构图 阅读详情

相关推荐

测站坐标系、地心非惯性系、经纬高互转

目录 一、经纬高转直角坐标系互转 1.1 python代码 二、wgs84转cgcs2000的转换矩阵如下 虽然cgcs2000与wgs84差别很小,但是我比较较真,还是做了两个坐标系的转换。 一、经纬高转直角坐标系互转 此处可参考链接(百度文库用手机浏览器可以打开看全部的): (1)第四章地球椭球及其数学详解 (2)第四章椭球数学变换16节 (3)大地测量学基础[1](7)(控制) 转换公式如下: LBH转XYZ: a为半长轴,e为偏心率 XYZ转LBH: a为半长轴

${王小贱}的博客 2万+

浅析RocketMQ-存储文件

CommitLog,Comsumequeue,Index

起风 1145

地震勘探中的频谱分析:从基础到应用

本文深入探讨了地震勘探中的频谱分析技术,从基础原理到实际应用。通过傅里叶变换等工具,频谱分析能有效识别不同地震波的频率特征,指导数据采集和处理。文章结合油田勘探案例,展示了如何利用振幅谱和相位谱提升信噪比,并介绍了智能滤波等前沿技术在地震数据处理中的应用。

weixin_42557830的博客 406

rocketmq架构和数据存储

注意: 1、nameServer1 和nameServer2 是相互独立的,这点跟 zookeeper集群不一样 2、每个broker都要配置 nameServer 下所有的节点,注册节点信息,topic信息,队列信息 3、节点 broker.name相同的是 同一个小集群,其中broker.id=0 是master节点,broker.id非0的是slave节点 4、offset存放在broker中 5、producer,comsumer会间隔30s 从nameServer中 把最新的路由...

beiduofen2011的专栏 1913

[模型部署]-[LLM]昇腾部署Qwen3-Coder-30B-A3B-Instruct

摘要:本文介绍了在Ascend NPU上部署Qwen3-Coder-30B-A3B-Instruct大模型的实践过程。通过vLLM-Ascend框架,详细说明了环境准备(CANN 8.1、PyTorch-NPU 2.5.1等)、模型下载、容器启动及服务部署步骤,包括vLLM服务的启动参数配置和接口测试方法。测试结果显示在当前2卡910B3配置下性能表现仅为8token/s(1并发),并指出流式调用时存在无法输出usage信息的问题。该方案为Ascend平台私有化部署大模型推理服务提供了参考实现。

1668

10.2 在新能源、储能及电网节点的应用实践

构网型变流器技术在电力系统中的应用进展 构网型变流器技术正从理论研究走向规模化工程应用,为新能源并网提供主动支撑能力。该技术在光伏电站采用"部分构网"混合架构,由构网单元实现黑启动和弱网稳定;在风电场利用叶轮动能提供惯量响应。储能系统是理想的构网载体,可提供快速调频和动态电压支撑。在电网节点,构网型STATCOM可增强弱电网电压稳定性,大容量变流器可替代传统调相机。当前面临标准滞后、宽频振荡风险等共性挑战,需在可靠性、经济性间取得平衡。系统级协调控制和精确阻抗建模是应用成功的关键。

技术工作者 1109

RocketMQ源码-broker 消息接收流程(写入commitLog)

处理消息接收的底层服务为 netty,在BrokerController#start方法中启动netty服务中,处理消息接收的channelHandler为NettyServerHandler,最终会调用SendMessageProcessor#processRequest来处理消息接收消息接收流程的最后,MappedFile#appendMessage(...)方法会将消息内容写入到commitLog文件中。

mxt51220的博客 695

CIC-IDS数据集特征介绍

###1、简介 通信安全机构(CSE)与加拿大网络安全研究所(CIC)合作项目,该项目对自1998年以来现有的11个数据集的评估表明,大多数数据集(比如经典的KDDCUP99,NSLKDD等)已经过时且不可靠。其中一些数据集缺乏流量多样性和容量,一些数据集没有涵盖各种已知的攻击,而另一些数据集将数据包有效载荷数据匿名化,这不能反映当前的趋势。有些还缺少特征集和元数据。 CIC-IDS-2017数据集包含良性和最新的常见攻击,类似真实世界数据(PCAPs)。 它的数据采集截至2017...

蓝亚之舟的博客 3万+

RocketMQ消息存储结构简介--CommitLog

RocketMQ消息存储是整个系统的核心,直接决定着吞吐性能和高可用性。RocketMQ存储消息并没有借助oracle、mysql等关系型数据库,而是直接操作文件。借助java NIO的力量,使得I/O性能十分高。当消息来的时候,顺序写入CommitLog。为了Consumer消费消息的时候,能够方便的根据topic查询消息,在CommitLog的基础上衍生出了CosumerQueue文件,存放了...

GAMELOFT9----纸上得来终觉浅,绝知此事要躬行 4232

ROS2实战:构建模块化启动文件(launch file)以驱动复杂机器人系统

本文详细介绍了ROS2中构建模块化启动文件(launch file)的最佳实践,帮助开发者高效管理复杂机器人系统的节点启动。通过功能分解、参数化设计和嵌套启动等技术,实现批量管理、依赖控制和配置统一,显著提升系统稳定性和调试效率。文章包含实战代码示例和工程化建议,特别适合自动驾驶、物流机器人等场景应用。

weixin_28744613的博客 214

GStreamer —— 2.1、Windows搭建GStreamer环境,Qt加载GStreamer库后运行 - “教程1:Hello world!“(附:完整源码)

GStreamer —— 2、Windows搭建GStreamer环境,Qt加载GStreamer库后运行"教程1:Hello world!"

796

RocketMQ原理解析-broker 2.消息存储

Rocketmq的消息的存储是由consume queue和 commitLog 配合完成的 1)  consume queue 消息的逻辑队列,相当于字典的目录用来指定消息在消息的真正的物理文件commitLog上的位置, 每个topic下的每个queue都有一个对应的consumequeue文件。 文件地址:${user.home} \store\consumequeue\${topic

gh670011677的博客 311

DDR5 的 PI: DIMM 上 PMIC,正在制造一批“新型 EMI 问题”

DDR5 的 PI,不再只是“供电设计”,而是一次“噪声管理设计”。电压稳定本地调节高频噪声EMI 风险系统不确定性DDR5 真正难的地方,不是跑起来,而是——在最差条件下,它还能不能一直跑。而 DIMM 上那颗 PMIC,正是你绕不开的关键角色。

weixin_43199439的博客 179

【RocketMQ】消息的存储设计

RocketMQ因为有高可靠性的要求(宕机不丢失数据),所以数据要进行持久化存储。所以RocketMQ采用文件进行存储。

morris 1万+

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

RocketMQ消息的存储结构

RocketMQ就是采用文件系统的方式来存储消息,消息的存储是由ConsumeQueue和CommitLog配合完成的。CommitLog是消息真正的物理存储文件。ConsumeQueue是消息的逻辑队列,有点类似于数据库的索引文件,里面存储的是指向CommitLog文件中消息存储的地址。 每个Topic下的每个Message Queue都会对应一个ConsumeQueue文件,文件的地址是:${store_home}/consumequeue/${topicNmae}/${queueId}/${fil.

Leon_Jinhai_Sun的博客 264

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

rocketmq存储消息怎么存的 存在哪

rocketmq消息存储在哪里

自救 唯有自强 531

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

rocketmq

最近在迁移项目的时候,顺带研究了一下rocketmq这个支持消息持久化的队列模型的消息中间件,之前也接触过一些像activemq,rabbitmq等中间件,但没有深入了解。 1. 什么是消息中间件 它采用高效可靠的传递机制进行平台无关的数据传递,通常消息队列利用异步的方式与服务端进行交互,适用于实时性不太高的场景。一般是一个队列模型的消息中间件,其主要解决异步解耦,挡住前端的数据洪

never_break_heart的博客 414

RocketMQ:CommitLog、ConsumeQueue、MessageQueue概念

📌 类比:MessageQueue 像快递公司分的投递路线(Route),每个快递员负责一条路线(Queue),而实际快递包裹都存放在仓库(CommitLog)里,通过路线单(ConsumeQueue)才能取出来。RocketMQ 的消息都是统一顺序追加到 CommitLog 里,ConsumeQueue 是按 Topic+QueueId 建立的稀疏索引,指向 CommitLog 的物理偏移量。📌 类比:像是一个巨大的按时间追加的“总账本”,所有消息都先记账到这里。RocketMQ 里。

H_porridge的博客 596

《RocketMq》二、存储篇

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34149796的博客 114

RocketMQ——消息的存储

RocketMQ的消息存储是由consume queue和commit log配合完成的。1、Consume Queueconsume queue是消息的逻辑队列,相当于字典的目录,用来指定消息在物理文件commit log上的位置。我们可以在配置中指定consumequeue与commitlog存储的目录每个topic下的每个queue都有一个对应的consumequeue文件,比如:${roc...

东天里的冬天 6765

RocketMQ 的消息是如何进行存储的?

RocketMQ是采用分布式存储的方式来存储消息的。每个Broker的存储结构主要包括:CommitLog、ConsumeQueue和IndexFile。RocketMQ通过这种分布式存储方式可以高效地存储和访问大量消息,同时也具有良好的可扩展性和可靠性。

越努力越幸运。 699

一文搞懂 RocketMQ 消息模型:Topic、Queue、Partition 底层逻辑

RocketMQ的消息模型由Topic、Queue和Partition构成,实现高效的消息分类、存储和分发。Topic作为逻辑分类标识,实现业务解耦和路由隔离;Queue是物理存储单元,通过多队列并行处理提升吞吐量;Partition是Queue的通用概念表达。消息流转中,Topic负责分类路由,Queue实现并行存储消费。RocketMQ采用"CommitLog+ConsumeQueue"的混合存储设计,兼顾写入效率和查询性能。

码路同行 930

RocketMQ系列---RocketMQ原理及架构

RocketMQ 核心组件图 RocketMQ是开源的消息中间件,它主要由NameServer,Producer,Broker,Consumer四部分构成。 NameServer:NameServer主要负责Topic和路由信息的管理,功能类似Dubbo的zookeeper。 Producer:消息生产者,负责产生消息,一般由业务系统负责产生消息。 Broker:消息中转角色,负...

谈少华的博客 4952

RocketMQ 消息存储机制 CommitLog和ConsumerQu

摘要:RocketMQ通过CommitLog文件存储所有消息,采用顺序写入提升性能。为优化消费效率,引入ConsumeQueue作为索引,按Topic/QueueId组织,记录消息在CommitLog中的物理偏移量。CommitLog默认1G大小,写满后创建新文件;ConsumeQueue采用定长设计(20字节/条目),实现快速检索。这种物理存储+逻辑索引的架构既保证了消息持久化,又提升了消费性能,同时支持消费者偏移量管理以实现故障恢复。

小楼一夜听春雨,深巷明朝卖杏花 3290

RocketMQ 消息存储

目前的 MQ 中间件从存储模型来看 ,分为需要持久化和不需要持久化的两种模型,现在大多数的 MQ 都是支持持久化存储的,比如 ActiveMQ 、 RabbitMQ 、 Kafka,RocketMQ ,而 ZeroMQ 却不需要支持持久化存储 。 然而业务系统也大多需要 MQ 有持久存储的能力 ,能大大增加系统的高可用性 。 从存储方式和效率来看,文件系统高于 KV 存储, KV 存储又高于关系型数据库,直接操作文件系统肯定是最快的,但可靠性却是最低的,而关系型数据库的性能和可靠性与文件系统恰恰相反,第 4

chenbin1991smile的博客 603
上一篇: mac的crontab没有执行的原因
下一篇: RocketMQ消息存储之刷盘机制(原理篇)
datastructure18
博客等级 码龄19年 6粉丝 10原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值