基础编程学习快乐每一天
首页
留言
Siddim.com
当前位置:
首页
>
编程知识库
>
后端开发知识
>
面试官:Kafka和RocketMQ有什么区别?
面试官:Kafka和RocketMQ有什么区别?
阅读
2
2021-10-15
MQ
全称(
message
queue
)消息队列,一个用于接收消息、存储消息并转发消息的中间件
多用于解决异步、削峰、解耦等场景,是能接收消息并转发消息
异步:比如
A
服务做了什么事情,异步发送一个消息给其他
B
服务。
削峰:有些服务(秒杀),请求量很高,服务处理不过来,那么请求先放到消息队列里面,后面按照能力处理,相当于蓄水池
应用解耦、消息通讯等等
总之
MQ
是可以存放消息并转发消息的中间件,场景取决于拿这个能力去解决什么问题
MQ概念模型
MQ
向别人承诺的场景是接收消息,存储,并可以转发消息
接收消息
在发送消息的时候,指明我要发送给谁,就像发送短信一样,你需要指明你要发送给谁?
这种方案在使用中是有问题的,因为在现在业务很多场景中, 发送方其实根本不知道对方是谁,他只是将自己的状态发送出来,那么谁需要这个消息,谁就接收,第二个如果指明了接收方,那么以后增加一个接收方就要改一下配置或者代码,将发送消息的人跟接收消息的人绑定在一起了
那么有没有方案,解耦的最好办法就是中间人,也叫中间层,我只发送给第三方,谁要消息,问第三方要,那么相当于我把发送的目标改为发送给第三方,这里的第三方就是
mq
,为了说明说明发送的地方,
mq
引入了
topic
的概念,发送方把消息发送到
mq
指定的一个通道中,以后谁想要这个消息,就跟
mq
说我想要这个通道的消息,也就是发送方发送的消息。
消费消息
消费消息,那么同理的一个问题,谁消费消息,为了说明那么
mq
需要引入一个概念,叫做消费者,也就是消费消息的服务,否则没有办法来区分是谁在接收消息,消费者通过网络接收消息就可以了,中间的细节我们先不探讨。
那么问题来了,消费者怎么说明消费谁的消息,上文已经说了,通过指明
mq
的
topic
,来决定我要哪一类消息。
至此我们总结一下最后的模型
也就是最后生产者和消费者通过
MQ
的
topic
概念来实现解耦。
存储
说到存储,其实效率才是最主要的,容量不是我们关心的,但是说到存储,不只是
mq
,所有需要高效率的存储其实最后利用的核心都是一样的。
随机写转换成顺序写
集中刷盘
为什么随机写要转换为顺序写?
现在主流的硬盘是机械硬盘
机械硬盘的机械结构一次读写时间 = 寻道时间 旋转延迟 读取数据时间
那么寻道时间比较长,如果是顺序写,只需要一次寻道时间,关于机械硬盘整个过程,读者可自行
google
。
为什么集中刷盘?
因为每次刷盘都会进行系统调用,第二还是跟硬盘的本身属性有关,无论是机械硬盘还是
ssd
按照一定块刷盘会比小数据刷盘效率更好。推荐:
Java
进阶视频资源
kafka
为什么先说
kafka
的存储,因为
kafka
是第一个高性能的消息中间件,其中
rocketmq
也是借鉴于它,所以我们先说
模型变化图
1
、为什么引入消费组概念?
上一次模型图我们还没有消费组,那么引入消费组,是因为现在一个服务都有很多实例在运行,消费组是对这群一群机器的一个划分,他还是一个概念而已。
2
、
mq
内部也发生了变化,一个
topic
后面又对应了很多
partition
,
partition
也是一个概念,他只不过是把一个
topic
分成了很多份,每一份叫一个
partition
,你高兴也可以叫他
xxx
,那么我们来说说为什么要分成很多份,一份不行吗?
因为现在一个服务有很多实例在运行,如果
topic
只有一份的话,那么所有的实例都会来消费消息,并且都是抢占我们一个
topic
,这不可避免引入了多实例竞争,以及他们之间怎么协调,一堆问题需要关注解决,现在我把
topic
分成了很多份,每一份只给一个实例,那么就不会引入各实例之间的竞争问题了,简化了
mq
的问题。
3
、生产组的引入也是一样的,只不过是一组机器的一个概念,一个逻辑的划分,生产者发送消息原先是发往
topic
,那么现在
topic
分成了很多份,生产者发送消息,需要说明发往哪个
partition
或者随意分配都可以,只不过最终发送的消息,会到一个
topic
下的一份里面。无论使用哪种映射方式都可以。
那么模型出来了,我们说说存储的问题。
对于
kafka
,一个
partition
对应一个文件,每次消息来都是顺序写这个文件。并且是定时刷盘,而不是每次写都刷盘,所以
kafka
的写非常高效。
RocketMQ
rocketmq
借鉴于
kafka
,所以存储借鉴了
kafka
,但是
rocketmq
不是仅仅把
partition
改成了
ConsumeQueue
,原先
kafka
,里面
partition
存储的是整个消息,但是现在
ConsumeQueue
里面是存储消息的存储地址,但是不存储消息了;
现在每个
ConsumeQueue
存储的是每个消息在
commitlog
这个文件的地址,但是消息存在于
commitlog
中
也就是所有的消息体都写在了一个文件里面,每个
ConsumeQueue
只是存储这个消息在
commitlog
中地址。推荐:
Java
进阶视频资源
存储对比
1、消息体存储的变化
那么我们先来看看
kafka
,假设
partition
有
1000
个,一个
partition
是顺序写一个文件,总体上就是
1000
个文件的顺序写,是不是就变成了随机写,所以当
partition
增加到一定数目后,
kafka
性能就会下降。而
rocketmq
是把消息都写到一个
CommitLog
文件中,所以相当于一个文件的顺序写;
2、为什么索引文件(ConsumeQueue)的增加对性能影响没有那么partition大?
(
kafka
也有索引文件,在这里只是想说明索引文件的增加跟
partition
增加的区别)
虽然
rocketmq
是把消息都写到一个
CommitLog
文件中,但是按照上面的实例会有
1000
个
ConsumeQueue
,也就是一千个文件,那么为什么就没有把顺序写变成随机写,带来性能的下降呢?首先就要介绍
linux
的
pagecache
我们平常调用
write
或者
fwrite
的时候,数据还没有写到磁盘上,只是写到一个内核的缓存(
pagecache
),只有当我们主动调用
flush
的时候才会写到硬盘中。或者需要回写的
pagecache
占总内存一定比例的时候或者一个应该回写的
page
超过一定时间还没有写磁盘的时候,内核会将这些数据通过后台进程写到磁盘中(总结就是达到一定比例,或者多长时间还没有回写,会被内核自动回写)。
然后我们现在来看看为什么大量索引文件的顺序写没有像
partition
一样导致性能明显下降。
ConsumeQueue
只存储了(
CommitLog
Offet
Size
Message
Tag
Hashcode
),一共
20
个字节,那么当
commitlog
定时任务刷盘之后,应该回写的
pagecache
的比例就会下降很多,那么
ConsumeQueue
的部分可以不用刷盘,就相当于
ConsumeQueue
的内容会等待比较长的时间聚合批量写入,而
kafka
每个
partition
都是存储的消息体,因为消息体都相对较大,基本在
kb
之上。
当一个
partition
刷盘的时候,应该回写的
pagecache
的比例降低的并不多,不能阻止其他
partition
的刷盘,所以会大量存在多个
partition
同时刷盘的场景,变成随机写。但是
rocketmq
消息都会写入一个
commitLog
,也就是顺序写。
所以总结如下:
1
、
consumerQueue
消息格式大小固定(
20
字节),写入
pagecache
之后被触发刷盘频率相对较低。就是因为每次写入的消息小,造成他占用的
pagecache
少,主要占用方一旦被清理,那么他就可以不用清理了;
2
、
kafka
中多
partition
会存在随机写的可能性,
partition
之间刷盘的冲撞率会高,但是
rocketmq
中
commitLog
都是顺序写。
感谢阅读,希望对你有所帮助 :)
来源:
blog
.
csdn
.
net
/
loulanyue
_/
article
/
details
/
89424013
以上数据来源于网络,如有侵权,请联系删除。
上一篇:
面试官:说说 HTTPS 是如何保证传输安全的?
下一篇:
面试官:MySQL和Hbase的区别是什么?各自适用什么场景。
评论
(0)
提交
类别
基础编程学习
HTML
PHP
Python
编程知识库
后端开发知识
热门文章
Java并发中的同步容器与并发容器,你了解多少?
Innodb中的事务隔离级别和锁的关系,难倒一半面试者!
SpringBoot + minio实现分片上传、秒传、续传
面试官:你知道消息队列如何保证数据不丢失吗?
JAVA知识 Java8新特性
面试官:谈谈为什么要限流,有哪些限流方案?
说说动态代理与静态代理区别
面试官:思考Tomcat 类加载器为什么要违背双亲委派模型?
boot-admin 基于SpringBoot的后台权限管理系统,可作为脚手架,用于快速搭建项目
SpringBoot+Vue+App+硬件实现智能家居系统项目