当前位置:   article > 正文

JAVA面试题分享一百五十六:RocketMQ和Kafka的区别?_kafka和rocketmq对比面试

kafka和rocketmq对比面试

目录

一、什么是MQ

二、MQ概念模型

三、存储

四、kafka

五、RocketMQ

六、相同之处

七、不同之处

一、什么是MQ

全称(message queue)消息队列,一个用于接收消息、存储消息并转发消息的中间件

多用于解决异步、削峰、解耦等场景,是能接收消息并转发消息

  • 异步:比如A服务做了什么事情,异步发送一个消息给其他B服务。
  • 削峰:有些服务(秒杀),请求量很高,服务处理不过来,那么请求先放到消息队列里面,后面按照能力处理,相当于蓄水池
  • 应用解耦、消息通讯等等

总之MQ是可以存放消息并转发消息的中间件,场景取决于拿这个能力去解决什么问题

二、MQ概念模型

MQ向别人承诺的场景是接收消息,存储,并可以转发消息

接收消息

在发送消息的时候,指明我要发送给谁,就像发送短信一样,你需要指明你要发送给谁?

这种方案在使用中是有问题的,因为在现在业务很多场景中, 发送方其实根本不知道对方是谁,他只是将自己的状态发送出来,那么谁需要这个消息,谁就接收,第二个如果指明了接收方,那么以后增加一个接收方就要改一下配置或者代码,将发送消息的人跟接收消息的人绑定在一起了

那么有没有方案,解耦的最好办法就是中间人,也叫中间层,我只发送给第三方,谁要消息,问第三方要,那么相当于我把发送的目标改为发送给第三方,这里的第三方就是mq,为了说明说明发送的地方,mq引入了topic的概念,发送方把消息发送到mq指定的一个通道中,以后谁想要这个消息,就跟mq说我想要这个通道的消息,也就是发送方发送的消息。

消费消息

消费消息,那么同理的一个问题,谁消费消息,为了说明那么mq需要引入一个概念,叫做消费者,也就是消费消息的服务,否则没有办法来区分是谁在接收消息,消费者通过网络接收消息就可以了,中间的细节我们先不探讨。

那么问题来了,消费者怎么说明消费谁的消息,上文已经说了,通过指明mq的topic,来决定我要哪一类消息。

至此我们总结一下最后的模型

也就是最后生产者和消费者通过MQ的topic概念来实现解耦。

三、存储

说到存储,其实效率才是最主要的,容量不是我们关心的,但是说到存储,不只是mq,所有需要高效率的存储其实最后利用的核心都是一样的。

  • 随机写转换成顺序写
  • 集中刷盘

为什么随机写要转换为顺序写?

  1. 现在主流的硬盘是机械硬盘
  2. 机械硬盘的机械结构一次读写时间 = 寻道时间 + 旋转延迟 + 读取数据时间

那么寻道时间比较长,如果是顺序写,只需要一次寻道时间,关于机械硬盘整个过程,读者可自行google。

为什么集中刷盘?

因为每次刷盘都会进行系统调用,第二还是跟硬盘的本身属性有关,无论是机械硬盘还是ssd按照一定块刷盘会比小数据刷盘效率更好。

四、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中地址。

六、相同之处

  • 两者底层原理有很多相似之处,RocketMQ借鉴了Kafka的设计。
  • 两者均利用了操作系统Page Cache的机制,同时尽可能通过顺序io降低读写的随机性,将读写集中在很小的范围内,减少缺页中断,进而减少了对磁盘的访问,提高了性能。

七、不同之处

1、存储形式

  • Kafka采用partition,每个topic的每个partition对应一个文件。顺序写入,定时刷盘。但一旦单个broker的partition过多,则顺序写将退化为随机写,Page Cache脏页过多,频繁触发缺页中断,性能大幅下降。
  • RocketMQ采用CommitLog+ConsumeQueue,单个broker所有topic在CommitLog中顺序写,Page Cache只需保持最新的页面即可。同时每个topic下的每个queue都有一个对应的ConsumeQueue文件作为索引。ConsumeQueue占用Page Cache极少,刷盘影响较小。

2、存储可靠性

  • RocketMQ支持异步刷盘,同步刷盘,同步Replication,异步Replication。
  • Kafka使用异步刷盘,异步Replication。

3、顺序消息

Kafka和RocketMQ都仅支持单topic分区有序。RocketMQ官方虽宣称支持严格有序,但方式为使用单个分区。

4、延时消息

  • RocketMQ支持固定延时等级的延时消息,等级可配置。
  • kfaka不支持延时消息。

5、消息重复

  • RocketMQ仅支持At Least Once。
  • Kafka支持At Least Once、Exactly Once。

6、消息过滤

  • RocketMQ执行过滤是在Broker端,支持tag过滤及自定义过滤逻辑。
  • Kafka不支持Broker端的消息过滤,需要在消费端自定义实现。

7、消息失败重试

  • RocketMQ支持定时重试,每次重试间隔逐渐增加。
  • Kafka不支持重试。

8、DLQ(dead letter queue)

  • RocketMQ通过DLQ来记录所有消费失败的消息。
  • Kafka无DLQ。Spring等第三方工具有实现,方式为将失败消息写入一个专门的topic。

9、回溯消费

  • RocketMQ支持按照时间回溯消费,实现原理与Kafka相同。
  • Kafka需要先根据时间戳找到offset,然后从offset开始消费。

9、事务

  • RocketMQ支持事务消息,采用二阶段提交+broker定时回查。但也只能保证生产者与broker的一致性,broker与消费者之间只能单向重试。即保证的是最终一致性。
  • Kafka从0.11版本开始支持事务消息,除支持最终一致性外,还实现了消息Exactly Once语义(单个partition)。

10、服务发现

  • RocketMQ自己实现了namesrv。
  • Kafka使用ZooKeeper。

11、高可用

  • RocketMQ在高可用设计上粒度只控制在Broker。其保证高可用是通过master-slave主从复制来解决的。
  • Kafka控制高可用的粒度是放在分区上。每个topic的leader分区和replica分区都可以在所有broker上负载均衡的存储。
  • Kafka的这种设计相比RocketMQ这种主从复制的设计有以下好处:
    • Kafka中不需要设置从broker,所有的broker都可以收发消息。负载均衡也做的更好。
    • Kafka的分区选举是自动做的,RocketMQ需要自己指定主从关系。
    • Kafka分区的复制份数指定为N,则可以容忍N-1个节点的故障。发生故障只需要分区leader选举下即可,效率很高。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/517844
推荐阅读
相关标签
  

闽ICP备14008679号