RocketMQ高性能从何谈起,数据又存放在哪?

今天我们再来聊一聊 RocketMQ,经过前面两章的了解,相信大家对于 RocketMQ 的基本架构以及实现消息队列的两种模式都已经很清楚啦。

那我们今天再来探讨一个问题,那就是:都说哦 RocketMQ 是高性能,那他为什么这么快?到底是怎么做到的?

先问大家一个问题:你觉得消息队列可以用到什么场景呢?

就不卖关子了,我们大学毕业的时候肯定有过这种经历,就是在论文查重网站上查重,想想全国的大学查重时间基本上都是那几个月,我们提交自己的论文之后,系统就会弹出来一条消息:当前业务繁忙,预计还有 xx 分钟出结果…或者其他的话术,反正大概都是这个意思。等过一会我们的查重结果就出来啦~

图片[1]-RocketMQ高性能从何谈起,数据又存放在哪?-编程社

那为什么要让我们等呢?当然扫库肯定是要时间的,但也不至于那么久吧?前面提到了,全国的大学基本上查重的时间都集中在那么几个月中,这个不可避免的就是,流量大!

因为流量大,我们的论文(消息)肯定就要排队,不然那么多请求直接给网站冲爆,大家都别用!所以大概率肯定是有用到消息队列的。

上面的场景就是:削峰填谷。当然消息队列肯定不止这一个作用哈。

根据上面描述的这样,那就非常完美了呀。用户的消息放在队列里面,排队消费,降低对系统的冲击,Nice!

但是哈,万一系统寄了,重启之后,用户存在消息队列中的数据丢失了,没了。怎么办哪?联系用户重新发消息嘛?哈哈,开什么玩笑呢。

那还有其他什么办法呢?

小 A:我知道!把消息存储在 MySQL 数据库里面,这样即便重启之后数据丢失,也可以在 MySQL 中“捞”出来数据重新消费。

是可以没错,但是又多涉及到了一层呀,本来就是一个简单的消息队列。多加了数据库,是不是又会变得复杂了呢?再者就是,你仔细想想 MySQL(或者其他数据库)性能好么?我看未必吧?如果性能好,要缓存干嘛?

小 A:防止并发请求将数据库搞噶。

当然是因为 MySQL 数据库是要和硬盘打交道的。读写消息是很慢的(相比内存)。你读写消息都要“半天”,那我 RocketMQ 的高性能从何体现?嗯?

小 A:那 MySQL 是要和硬盘打交道,我用 Redis 给它存起来,嘿嘿,基于内存,肯定好使。

不!更不行了,读写的速度是快了,但是不可靠。

而且如果说线上场景出问题了,那你说说我到底是应该定位 MySQL?Redis?还是消息队列本身?这无疑增加了维护和学习的成本。

那到底怎么办呢?

答案就是存在硬盘上。你使用 MySQL 是不是在硬盘上存储数据;Redis 持久化是不是也是在硬盘上?那我们直接存在硬盘上不就好了。

commitLog

再介绍一个文件:commitLog。RocketMQ 的消息就是存储在 commitLog 中的,而且消息会以顺序写的形式存放在 commitLog 中。

图片[2]-RocketMQ高性能从何谈起,数据又存放在哪?-编程社

那顺序写是为了保证消息读写的时候可以更快一些,那为啥不同的 Topic 也都要存在一个 commitLog 中捏?根据 Topic 分开存放,不应该更符合逻辑嘛?

这里其实就涉及到硬盘的相关知识了。

硬盘是由磁头、磁头臂、磁盘等组成的,通过控制磁头臂来移动磁头扫描磁盘片获取数据的。当想要访问数据的时候,磁头移动到该数据的所处扇区即可读取到。

图片[3]-RocketMQ高性能从何谈起,数据又存放在哪?-编程社

这个图稍微画的有点抽象了。当然关于磁盘肯定不止这些知识的,像磁盘片中还有扇面、磁道、扇区、簇等等的概念,具体可以看看这方面相关的文章。

我们回过来继续说。那么如果数据存放在磁磁盘中是“相邻”的,那是不是读写的速度就非常快了。那怎么让他们相邻呢,就是顺序写入呗。所以 顺序的读和写 是非常快滴。

这也就解释了为什么不将 Topic 分开来进行存放,而是要写入一个 commitLog 文件中了。如果写入不同的文件中,就不会是顺序的了,那读写的效率就会大打折扣。

到这里就差不多讲完了,所以大家一提到这个就想到说什么用数据库存储或者什么其他的东西。要知道,一个优秀的中间件,是不会依赖第三方组件的,一旦引入,复杂度自然就提升了,也就没有什么所谓的高可用、高性能了。

© 版权声明
THE END
喜欢就支持一下吧
点赞9 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称

    暂无评论内容