RocketMq整体架构浅析

1,446 阅读8分钟

1:kafka,rabbitMq,rocketMq区别

kafka

吞吐量:kafka的的吞吐量是非常优秀的,在常规的机器上,一台机器也可以达到每秒十几万的QPS

性能: 性能也非常优秀,基本上发送消息给kafka都是毫秒级的

高可用:kafka支持集群部署,即使有一台机器宕机了,还是可以继续运行

缺点:功能单一,没有像延时消息,事务消息等功能

适用场景:用在用户的行为日志采集和运输上

rabbitmq

吞吐量:相比于kafka和rocketMq较低,如果遇到特别高的并发的话可能支持不le

高可用:RabbitMq支持集群部署,即使有一台机器宕机也可以继续提供服务

功能:可以保证数据不丢失,而且提供了很多高级功能,比如:延时消息,消息重试,死信等

缺点:源码是使用erlang编写的,阅读源码困难

RocketMq

吞吐量:rocketMq的吞吐量也是很高的,而且也可以做到数据不丢失

高可用:支持集群部署

功能:也提供了很多的高级功能,比如:延时消息,事务消息等,最主要是源码是使用Java来写
的,可以方便的阅读,并且根据需求去修改它的源代码

2:RocketMq是如何承载高并发访问的

一台RocketMq可以承载十几万的QPS,如果现在有几十万的QPS,那么就会集群部署,比如部署了3台,现在有30万的QPS,那么每台的并发量就是10万,如下图:

WeChat63901bb4955a8d9a563104c71bc3905a.png

3:RocketMq如何存储海量消息

MQ收到消息并不会马上就被消费,而是会先持久化到本地磁盘,然后等待消费者来消费,那么一台机器的存储空间是有限的,比如一台机器只能存储1000万条消息,如果现在有3000万条消息,那么一台机器肯定是存储不了的,所以这时候需要集群化部署,然后每台机器都存储一部分数据,如果还有数据,我们只需要增加一个节点来保存就行了

WeChat9e14ac7531cdb3131041680549483065.png

4:高可用-如果Broker挂了怎么办

每台机器部署的RocketMq的进程就代表一个Broker。上面说到我们的消息是存储在Broker中的,如果这时候Broker挂了,那么数据也就没了,这该怎么办??

RocketMq采用了Broker主从架构及多副本策略,也就是说Broker是有Master,Slave二种角色的,Master Broker收到消息之后会同步给Slave Broker,这样Slave就有了跟Master一样的数据,即使Master挂了也不会导致数据丢失

5:消息路由

对于系统来说,我们要将消息发送到MQ中,还要从MQ中消费消息,那么系统是怎么知道有哪些Broker的呢??

所以RocketMq有一个NameServer的概念,它也是独立部署在几台机器上的,所有的Broker都会往这个NameServer上注册自己的信息,不管是Master Broker还是Slave Broker都会注册自己的信息,这样NameServer就可以知道所有的Broker,后续无论是发送消息到MQ还是从MQ中消费消息都可以从NameServer中找到这些Broker

6:NameServer到底可以部署几台机器

如果现在只部署一台NameServer,那么还是存在单点问题的,如果此时这台NameServer挂了,那么无论是生产者还是消费者都不能拿到Broker的信息了

NameServer也是支持集群化部署的,这样每个Broker都会往每一个NameServer上去注册自己的信息,这样即使有一台NameServer挂掉了,还有一台NameServer可以继续提供服务

7:系统如何从NameS而ver获取Broker信息

第一种:NameServer推送,也就是NameServer主动向系统发送最新的Broker信息,但是这显然是不合理的,因为NameServer怎么知道你有哪些系统呢

第二种:系统主动去NameServer获取最新的Broker信息,每个系统都会定时的发送请求去NameServer拉取最新的Broker的信息,不管是生产者还是消费者,都会每隔一段时间就去NameServer拉取最新的Broker信息

8:NameServer如何感知Broker挂掉了

如果某一个Broker挂掉了,那么NameServer是如何感知的呢??

其实每个Broker都会每隔30s就会向所有的NameServer发送一次心跳,并且NameServer本身也会每隔10s就会去查一下是否有哪一个Broker 120s了还没有发送心跳,如果120s都没有发过心跳了,那就认为这个Broker已经挂了

9:Master Broker是如何将消息同步给Slave Broker的

Slave Broker会不停的发送请求到Master Broker去拉取消息,所以RocketMq中Master-Slave本身采取的是Pull模式拉取消息的

10:RocketMq实现了读写分离了吗

生产者发送一条消息到Master Broker之后,这条消息也会同步给Slave Broker,那么当消费者要消费消息的时候是从Master中拿消息还是从Slave拿消息呢??

其实都有可能,主要还是要根据Master Broker的情况来定,作为消费者首先会从Master Broker去获取消息,此时Master Broker会返回一批消息给消费者,在Master broker返回消息给消费者的同时,会根据Master Broker本身的负载情况和Slave Broker的同步情况,向消费者建议下次是从Master Broker拿消息还是从Slave Broker拿消息。

比如:Master Broker现在要接收很多生产者发送过来的消息,那么Master Broker本身的负载就已经很大了,如果还从Master Broker拿消息吗,那么只会让Master Broker的压力更大,所以Master Broker会建议消费者下次从Slave Broker拿消息

如果Master Broker现在有10万条数据,但是Slave Broker只同步了90万条,这时候还有10万条数据没有同步,那么这时候消费者还是会直接从Master Broker拿数据

11:如果Slave Broker挂掉了怎么办

有一点影响,如果Slave Broker挂掉了,那么消费者拿消息的时候会直接从Master Broker拿,这样会导致Master Broker的负载变大

12:如果Master Broker挂掉了怎么办

影响很大,在RocketMq4.5版本之前,都是用Slave同步数据,尽量保证数据不丢失,但是一旦Master挂掉了,Slave是没办法自动切换成Master的,这时候需要手动做一些操作,把Slave修改一些配置,然后重启Slave,将Slave切换成Master,是有点麻烦的,而且在切换过程中该Broker是不可用的

在RocketMq4.5之后,RocketMq支持了一种新的机制,叫做Dledger,这个东西是基于Raft协议实现的一个机制,把Dledger融入RocketMQ之后,就可以让一个Master 对应多个Slave,也就是一个Master Broker对应多个Slave Broker,然后多个Slave Broker会与Master Broker进行同步,如果这时候Master挂掉了,就可以在多个副本中,通过Dledger技术和Raft协议算法进行leader选举,然后将一个Slave Broker切换成Master Broker,然后这个Master Broker就可以继续对外提供服务了,整个过程也就只要十几秒就可以完成,所以在部署RocketMq的时候完全可以采用基于Dledger的部署方式

13:RocketMq发送消息的三种模式

1:同步方式

当我们通过SendResult result = producer.send(msg)发送消息到RocketMq,然后你会卡在这里,代码不能往下走,你要一直等到MQ返回一个结果给你,你拿到SendResult之后,接着你的代码才会继续往下走

2:异步方式

producer.send(message, new SendCallBack() {
​     public void onSuccess(SendResult result) {
​           //消息成功发送的到MQ的回调函数 
​     }
​     public void onException(Throwable e) {
​          //消息没有成功发送到MQ的回调函数
​     }
});

当你发送一条消息到MQ,上面的代码不会等到MQ返回结果,而是会继续往下执行,直到MQ返回结果之后,就会调用对应的回调函数

3:发送单向消息到RocketMq

 Producer.sendOneWay(msg);

意思就是你发送一个消息给MQ,然后代码就往下走,根本不会关注MQ有没有返回结果给你,
你也不需要返回结果,无论发送的消息是成功还是失败,都不关你的事

14:RocketMq消费者消费模式

1:Push消费模式

Broker会主动把消息发送给你的消费者,你的消费者是被动的接收Broker推送过来的消息,然后进行处理

2: Pull消费模式

消费者主动从Broker去拉取消息进行消费,消费者是主动的