RocketMQ面试题

6,924 阅读4分钟

1.请描述一下RocketMQ与kafka的区别?

RocketMQ是根据kafka的架构原型设计出来的,有很多地方都相似,consumer、producer、broker,甚至RocketMQ初期也是用zookeeper做注册中心。

首先RocketMQ吞吐量TPS是在10万级别,kafka到了百万级别,RocketMQ貌似比kafka的tps小
这是由消息存储架构决定的,kafka采用的是每个Partition(类比于RocketMQ的queue)一个文件,而RocketMQ采用的是所有topic都存储在一个文件commitLog(超过1个G会重建一个文件)。那mq中影响tps的两个关键因素:消息写入(生产)、消息读取(消费)。

  • 消息写入
    在这一块kafka和rocketmq设计和使用到的技术基本一致:
    1) 顺序写入
    2) 利用OS提供的pageCache来实现mmap(内存映射文件),java中是通过NOI提供的MappedByteBuffer类具体实现的
  • 消息读取
    两者都采用了一个技术叫做零拷贝,这样就不用先将磁盘内容从内核空间(磁盘的)拷贝到用户空间,再从用户空间拷贝到内核空间(socket的),而是直接从内核转到内核,java里面是通过NIO提供的FileChannel实现

由于RocketMQ所有topic消息都存在一个文件中,读取是根据consumerQueue文件里的offset去读取的,所以是随机读取。正因为此,RocketMQ的TPS不如kafka

除此之外还有一个原因:

kafka采用异步发送的机制,当发送一条消息时,消息并没有发送到broker而是缓存起来,然后直接向业务返回成功,当缓存的消息达到一定数量时再批量发送。此时减少了网络io,从而提高了消息发送的性能,但是如果消息发送者宕机,会导致消息丢失,业务出错,所以理论上kafka利用此机制提高了io性能却降低了可靠性

那RocketMQ为什么要这样设计?

  1. kafka中Producer调用发送消息接口,消息未发送到Broker,向业务返回成功,此时Producer宕机,会导致消息丢失,业务出错,这样看来kafak可靠性不如RocketMQ,这也是RocketMQ作为互联网金融业务的首选;
  2. kafka是一个分区一个文件。当topic过多,分区的总量也会增加,kafka中存在过多的文件,当对消息刷盘时,就会出现文件竞争磁盘,出现性能的下降。 而且,一个分区只能被一个消费组中的一个消费线程进行消费,因此可以同时消费的消费端也比较少。

其他区别请看这里

本文引用
blog.csdn.net/z69183787/a…
www.cnblogs.com/cai-cai777/…

RocketMQ为什么自研nameserver而不用zk?

  1. RocketMQ只需要一个轻量级的维护元数据信息的组件,为此引入zk增加维护成本还强依赖另一个中间件了。
  2. RocketMQ追求的是AP,而不是CP,也就是需要高可用。
  • zk是CP,因为zk节点间通过zap协议有数据共享,每个节点数据会一致,但是zk集群当挂了一半以上的节点就没法使用了。
  • nameserver是AP,节点间不通信,这样会导致节点间数据信息会发生短暂的不一致,但每个broker都会定时向所有nameserver上报路由信息和心跳。当某个broker下线了,nameserver也会延时30s才知道,而且不会通知客户端(生产和消费者),只能靠客户端自己来拉,rocketMQ是靠消息重试机制解决这个问题的,所以是最终一致性。但nameserver集群只要有一个节点就可用。

msgKey,msgId,offsetMsgId的区别

blog.csdn.net/prestigedin…
index file用来做索引的key,如果发送端设置了msg key,则用这个,如果没有,则用msgId,因为msgId是生产端生成的全局唯一id

消费offset管理

每次pull是根据上一次拉取的nextbegineOffset来确定这次拉取的offset,而只有等msg消费成功才会在下次pull或者定时的上报给broker,因为消费是并发的,所以不是按offset顺序消费的,每次上传连续的最后一个offset www.jianshu.com/p/b4970f59a…