图解RocketMQ之消息如何存储

news2024/9/23 17:25:46

大家好,我是苍何。

人一辈子最值得炫耀的不应该是你的财富有多少(虽然这话说得有点违心,呵呵),而是你的学习能力。技术更新迭代的速度非常快,那作为程序员,我们就应该拥有一颗拥抱变化的心,积极地跟进。

在学习 RocketMQ 的消息存储之前,我们已经学习了 topic 主题、消息模型、消息的过滤和重试等知识点。

这让我感觉自己富有极客精神,非常良好。

我好快乐

小伙伴们在继续阅读之前,我必须要声明一点,为一名负责任的技术博主,我是动了心的,这篇教程,小伙伴们读完后绝对会感到满意,忍不住无情地点赞,以及赤裸裸地转发

当然了,小伙伴们遇到文章中有错误的地方,不要手下留情,可以组团过来捶我,但要保证一点,不要打脸,我怕毁容。

我们都知道,消息队列一大核心功能是削峰填谷,也就是在大流量场景下(比如 12306 春运购票),将部分业务逻辑放在 MQ,等其慢慢处理,且给用户友好提示:

“您已加入候补队列,请耐心等待!”

在 MQ 中的消息,可以有条不紊的、均匀的消费,但需要保证消息存储的可靠性

不可能我加入候补半天,让我等,我等了 2 天,然后提示我压根没加入候补,这不是坑人吗?

mq宕机后消息都丢了

所以,我们需要动员脑子里所有脑细胞,仔细思考下,MQ 中的 broker 该如何存储消息才能防止消息丢失呢?

消息可以存 MySQL 吗

要防止数据不会在持久化的时候消失,很多的做法都是将数据库直接存在 MySQL,比如 Nacos 持久化、Redis 持久化。

那 RocketMQ 可以把消息存储在 MySQL 吗?

单纯从持久化来看,没问题,但消息可不单单是做持久化,需要满足削峰填谷需求,MySQL 性能就无法满足了。

如果 MySQL 可以,那我干嘛费老半天劲把消息丢到 MQ 呢?我直接丢 MySQL 处理不就得了?

这时估计 MySQL 他老人家也会想"合着折腾半天,最后又回到我这了是吧?"

消息可以存 MySQL 吗

消息可以存 Redis 吗

这个时候你聪明的脑袋瓜肯定灵机一动,那要想追求高性能,存 Redis 啊,Redis 贼快,而且还可以持久化,这下可以了吧?

Redis 就像是个 mini 冰箱,虽然取东西快,但空间有限。RocketMQ可是要处理海量消息的"大胃王",用硬盘这个"大冷库"才够塞。

Redis 虽然也能持久化,但更像是给冰箱拍照。RocketMQ 需要的是 365 天 24 小时不间断运转的"冷库"级别持久化。

处于性能的考虑,Redis 读写虽然很快,毕竟还是操作内存,但要在内存和磁盘间倒腾数据就慢了。

Redis说:臣妾做不到啊

还有一个核心问题是,如果真是把消息放 Redis 了,那又引入了第三方组件,合着,我想用个 RocketMQ,你还得硬要我搞个 Redis。Redis 要宕了,RocketMQ 也嗝屁了。

软件工程,不是越复杂越好,和生活一样,往往大道至简的东西才更优雅,故而 RocketMQ 是绝对不可能吧消息丢给 Redis 的。

消息存哪里

这时,你肯定会没耐心的对苍何想要拳打脚踢,说这么半天,那消息到底存在哪儿?

先说结论:消息存本地磁盘

是不是简单粗暴?反正最后不管是 MySQL 还是 Redis,持久化都要存磁盘,那我直接绕过中间商,不更优雅吗?

磁盘存储绕过中间商

问题很多的小明又问了,磁盘也不可靠啊,不是照样会损坏?

但现在服务器上都要做 RAID,有备份在,那如果服务器直接被炸了呢?(虽然这种概率很小)

那还可以多云融合(就是多个云服务器备份),异地容灾等,这里就不展开了,总之,道高一尺,魔高一丈。

极致的可靠是不存在的,我们只能在我们能想到的合理范围内做到可靠,这就是互联网。

你可能会问,存到磁盘上,那是如何存储的呢?

假如有很多个 topic,每个 topic 又有很多个队列,是每个 topic 一个文件?还是每个队列一个文件?

commitlog

为了保证 RocketMQ 的写性能,最好是将所有消息都放在一个文件,并顺序读、顺序写

如果不放在一个文件,硬盘的存储物理位置就不是连续的,能无法保证顺序写,这个时候写入后的物理位置其实就是随机的了。

顺序读写也是为了追求极致的性能,这个其实和 MySQL 的 redo log 有异曲同工之妙。

而这个存储消息的本地文件,就叫做 commitlog。位于 rocketmq/data 文件夹下面。

commitLog所在位置

当你用你粗壮的手准备打开这个文件时,发现是个二进制文件。

commitLog是个二进制文件

这也很好理解,使用二进制存储,一来节省存储空间,二来也能提高读取性能

要想打开读取这文件,可以借助 RocketMQ 自带的 mqadmin 来读取,比如:

# 使用rocketmq-tools查看消息
sh mqadmin queryMessageByKey -n <namesrvAddr> -t <topic> -k <messageKey>

当然也可以使用开源工具如 rocketmq-dump 来查看,小伙伴们可以亲自试试。

consumequeue

细心的小伙伴可能已经注意到除了 commitlog 还有一个文件 consumequeue,那这里面存的是啥子呢?

我们知道 commitlog 存的是消息的全量数据,那对于消费者来说,想要知道自己该消费哪条消息,我们在之前的文章中分析过,靠的是消费位点(comsumerOffset),也就是消息的记录。

这个 comsumerOffset 也是会落在磁盘持久化的。

commitlog 里面只有一个文件,里面存的是消息的全量信息,为了追求极致的性能体验,肯定是需要索引来进行查询。

consumequeue 存放的是起始偏移量和长度,相当于这个索引。

通过起始偏移量和长度可以查询 commitlog 中的全量消息信息。

为什么这么做呢?

文件下标对应关系

假设 commitlog 存了 2 条消息,分别是 ABC、012,那对应的文件内容是 ABC012,每个字节会对应一个下标,比如:

A:0
B:1

我们要想读到 ABC 这条消息,只需要知道起始的 A 对应的下标,以及消息的长度就可以拿到这条消息了。这个下标其实就是偏移量

通过起始下标和长度可以拿到消息

所以 consumequeue 中存的就是消息的起始偏移量和长度。

consumequeue存的是啥子?

那么现在我们来梳理下消息存储的流程吧:

RocketMQ 先将消息存到 commitlog,然后通过定时任务把消息的起始偏移量和长度存到 consumequeue,然后根据这两个数据定位到消息,在 consumequeue 其实就已经按照 topic 和队列分好了,查找起来也是相当快的。

消费者消费消息的时候,通过消费位点找到 consumequeue 里面的起始偏移量和长度,通过索引找到 commitlog 对应的全量消息,然后再消费。

消息存储和消费流程

消息索引

细心的小伙伴可能会注意到通过起始偏移量和长度来定位消息,着实有些慢,并不能快速查找到消息。

RocketMQ 提供了消息索引机制。5. x 中是位于 index 文件夹中,存放的就是索引信息。(这个索引更快👍)

消息索引

索引的内部通过数据槽来实现,感兴趣的小伙伴可以去了解下内部实现原理。

通常我们会将业务唯一 id 设置为索引,比如订单号,查询订单号就能立刻查询出当前订单的消息。

那么如何添加索引呢?

发送消息的时候,可以添加索引:

Message msg = new Message("TopicTest", "TagA", "Hello RocketMQ".getBytes());
msg.setKeys("yourKey");

broker 配置中需要做下设置:

messageIndexEnable=true
messageIndexSafe=false

最后

不得不说,一个优秀的中间件,往往会有很多精妙的设计,RocketMQ 的消息存储机制的设计就堪称完美。

当然,还有更多的细节,比如 commitlog 的加载流程、索引的存储结构,这些大家感兴趣的可以自行查阅资料哈。

好啦,今天的分享结束。

我是苍何,这是图解 RocketMQ 教程的第 8 篇,我们下篇见~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1982098.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

西安交通大学先进动力与新能源发展峰会举行

8月3日&#xff0c;西安交通大学第十届先进动力与新能源发展峰会暨西安交大先进动力校友会2024年年会在深圳举行。西安交通大学党委常委、副校长单智伟&#xff0c;南方科技大学清洁能源研究院院长、创新创业学院院长、澳大利亚国家工程院外籍院士刘科&#xff0c;西安交通大学…

抑制电机噪声的又一神器 -- 三线共模电感

概述 针对电机产品&#xff0c;尤其是三相无刷电机&#xff0c;如图1&#xff0c;其噪声源主要是电机的开关驱动模块&#xff08;具体可参阅另一篇文章“”&#xff09;&#xff0c;而一般的等效天线即为连接电机与驱动板的电机线&#xff08;等效天线、四分之一波长的理论解释…

R18 NTN中的Satellite switch with re-sync过程

更多精彩内容,请阅知识星球合集链接。该链接收录了目前知识星球所有内容,涵盖了5G相关领域的绝大多数知识点;主要以协议原文截图后进行解释讲解外加实网log对照为主,辅以星友问答等等精华内容。 合集链接如下(不用登录飞书即可查看):Docs 如果您对3GPP spec阅读有困扰; 如…

HTTPS 比 HTTP 更安全吗?这两种协议有什么区别?

在互联网的通讯过程中&#xff0c;HTTP&#xff08;超文本传输协议&#xff09;和HTTPS&#xff08;安全HTTP&#xff09;是两种最基本、最重要的通讯协议&#xff0c;它们在网络中都扮演着重要的角色。然而近年来&#xff0c;随着网络安全问题的日益突出&#xff0c;HTTPS的安…

测试人员怎么通过浏览器开发工具 Performance 分析性能

在现代Web开发中&#xff0c;性能优化是一个永恒的话题。对于测试人员来说&#xff0c;如何有效地使用浏览器开发工具中的Performance面板&#xff0c;进行性能分析和调优&#xff0c;是一项必备技能。本文将带你深入了解浏览器开发工具Performance面板的使用方法及其在性能测试…

OrangePi AIpro学习2 —— 配置昇腾DVPP环境

目录 一、clone需要运行的软件 二、运行corp程序 2.1 解决缺少sample_common.sh 2.2 解决缺少INSTALL_DIR环境变量 2.3 运行程序 三、测试其他程序 3.1 程序目录 3.2 程序注意事项 3.3 如何找出报错原因 一、clone需要运行的软件 1. 软件地址 samples: CANN Samples…

Docker 设置代理

Docker 设置代理 创建配置文件 sudo mkdir -p /etc/systemd/system/docker.service.d sudo touch /etc/systemd/system/docker.service.d/proxy.conf sudo vim /etc/systemd/system/docker.service.d/proxy.conf 编辑代理配置 #输入以下内容&#xff0c;其中代理改成自己的…

【大小球让球实战】——深度剖析足球大小球数据分析软件,找到一个临界点,把准确率提高到70%?

最近在跟一些圈内朋友聊天&#xff0c;发现每个人都有一套自己的玩球逻辑&#xff0c;比如有些人看亚盘&#xff0c;有些看欧盘&#xff0c;有些玩绝杀&#xff0c;有些看盘口&#xff0c;是否可以自定义的去玩球&#xff1f;结合多年的经验&#xff0c;把分析的过程大概写了一…

ESP32在ESP-IDF环境下禁用看门狗

最近使用了一款ESP32的开发板。但在调试时发现出现许多看门狗复位事件&#xff1a; E (8296) task_wdt: Task watchdog got triggered. The following tasks/users did not reset the watchdog in time: E (8296) task_wdt: - IDLE (CPU 0) E (8296) task_wdt: Tasks curre…

FFmpeg 7.0重大更新

0、维护工作 对于任何成熟的软件&#xff0c;每个版本必然包含大量的bugfix、cleanup。维护工作不会出现在Changelog中&#xff0c;不是吸引眼球的东西&#xff0c;但是人力投入的占比最高&#xff0c;是一个项目长期稳定的保证。 维护工作必须得提两个人&#xff0c;Andreas…

校园超市收银软件的挑战:双系统困境-亿发

在现代零售业中&#xff0c;高效的管理系统是确保业务顺利进行的关键。然而&#xff0c;对于学校直属管理的超市来说&#xff0c;选择合适的收银系统往往是一项挑战。由于缺乏能够同时满足收银和进销存管理需求的高适配性系统&#xff0c;许多学校超市不得不同时使用两套系统&a…

iPhone手机清理软件:让你的设备焕然一新

随着智能手机在我们生活中的地位日益重要&#xff0c;保持设备的最佳性能就显得尤为关键。对于iPhone用户而言&#xff0c;随着时间的推移&#xff0c;手机可能会因累积了过多的缓存文件、重复照片、未使用的应用和各种其他数据而变得缓慢。幸运的是&#xff0c;市面上有多种iP…

可以翻页、互动、留言和弹幕的仿真电子相册制作方法

​在数字化时代&#xff0c;仿真电子相册作为一种结合了翻页、互动、留言和弹幕等多种功能的创意表达形式&#xff0c;正逐渐成为人们记录生活和分享回忆的重要方式。本教程将介绍如何利用FLBOOK这款强大的电子相册制作工具&#xff0c;制作具有这些特性的令人印象深刻的作品。…

ICM-20948芯片详解(6)

接前一篇文章&#xff1a;ICM-20948芯片详解&#xff08;5&#xff09; 五、组件概览及详述 再次给出ICM-20948芯片的内部结构框图&#xff1a; 2. 组件详述 &#xff08;6&#xff09;辅助I2C串行接口 ICM-20948具有用于与外部传感器通信的辅助I2C总线。该总线有两种操作模…

实时采集同花顺要闻直播资讯

采集同花顺要闻直播资讯能实时掌握市场动态、政策变化及企业新闻&#xff0c;对投资者而言&#xff0c;有助于及时做出投资决策&#xff0c;把握市场机会&#xff0c;规避风险。对于研究机构和媒体&#xff0c;它提供一手资料&#xff0c;支持深度分析与报道。 采集网址&#x…

第 8 章 虚拟文件系统(7)

目录 8.5 标准函数 8.5.1 通用读取例程 8.5.2 失效机制 8.5.3 权限检查 8.6 小结 本专栏文章将有70篇左右&#xff0c;欢迎关注&#xff0c;查看后续文章。 8.5 标准函数 大多数文件系统中 file_operations 的 read&#xff0c;write 分别为&#xff1a; do_sync_read&am…

Android开发之事件分发

#来自ウルトラマンゼロ&#xff08;哉阿斯&#xff09; 1 Activity 构成 平常布局展示在ContentView中。 2 事件分发 事件分发的本质其实就是把事件&#xff08;Touch&#xff09;封装成 MotionEvent 类&#xff0c;然后传递给 View 的层级处理。 MotionEvent 事件类型主要有…

51单片机-第七节-DS1302实时时钟

一、DS1302介绍&#xff1a; 实时时钟芯片&#xff0c;可对年&#xff0c;月&#xff0c;日&#xff0c;周&#xff0c;时&#xff0c;分&#xff0c;秒计时&#xff0c;是一种集成电路。 二、DS1302原理&#xff1a; 1.寄存器定义&#xff1a; Command&#xff1a;操作模式…

MySQL:表的增删查改——CRUD(二)

本篇博客接上篇&#xff1a;MySQL&#xff1a;表的增删查改——CRUD&#xff08;一&#xff09;-CSDN博客 目录 1、查询&#xff08;Retrieve&#xff09; 1.1 条件查询&#xff1a;WHERE 1.1.1 比较运算符 1.1.2 逻辑运算符 1.1.3 查询语句的执行顺序 1.1.3 SQL代码示例…

小试牛刀-walletconnect二维码及交互

目录 1.编写目的 2.实现功能 3.功能详解 依赖组件 3.1 二维码生成 3.1.1 初始化SignClient 3.1.2 创建会话空间获取WC协议uri 3.1.3 生成二维码供用户扫描 3.1.4 等待扫描 3.2 发送交易事务 3.2.1 创建交易事务 3.2.2 向用户发送交易事务 3.3 签名事务 3.3.1 接收…