01.为什么要用RocketMq?
02.RocketMq的部署架构了解吗?
03.它有哪几种部署类型?分别有什么特点?
04.你自己部署过RocketMq吗?简单说一下你当时部署的过程
05.rocketmq如何保证高可用性?
06.rocketmq的工作流程是怎样的?
07.RocketMq使用哪种方式消费消息,pull还是push?
08.RocketMq如何负载均衡?
09.RocketMq的存储机制了解吗?
10.RocketMq的存储结构是怎样的?
11.RocketMq如何进行消息的去重?
12.RocketMq性能比较高的原因?
看的时候,建议大家不妨先看看问题,自己先尝试回答一下,再看答案。看看自己掌握得如何了 那准备好了的话,我们就要开始啦啊~01.为什么要用RocketMq?
总得来说,RocketMq具有以下几个优势:
02.RocketMq的部署架构了解吗?
这个是rocketMq的集群架构图,里面包含了四个主要部分:NameServer集群,Producer集群,Cosumer集群以及Broker集群03.它有哪几种部署类型?分别有什么特点?
RocketMQ有4种部署类型04.你自己部署过RocketMq吗?简单说一下你当时部署的过程
由于我们项目中主要使用rocketMq做链路跟踪功能,因此需要比较高的性能,并且偶尔丢失几条消息也关系不大,所以我们就选择多Master多Slave模式,异步复制方式进行部署 部署过程简单说一下: 我部署的是双master和双slave模式集群,并部署了两个nameserver节点 1)服务器分配 分配是两台服务器,A和B,其中A服务器部署nameserv1,master1,slave2;B服务器部署nameserv2,master2和slave1节点 2)broker的配置 分别配置rocketmq安装目录下四个配置文件:master1:/conf/2m-2s-async/broker-a.propertiesslave2:/conf/2m-2s-async/broker-b-s.propertiesmaster2:/conf/2m-2s-async/broker-b.propertiesslave1:/conf/2m-2s-async/broker-a-s.properties
总的思路是: a.master节点的brokerId为0,slave节点的brokerId为1(大于0即可); b.同一组broker的broker-Name相同,如master1和slave1都为broker-a; c.每个borker节点配置相同的NameServer; d.复制方式配置:master节点配置为ASYNC-MASTER,slave节点配置为SLAVE即可; e.刷盘方式分为同步刷盘和异步刷盘,为了保证性能而不去考虑少量消息的丢失,因此同意配置为异步刷盘
3)启动集群
a 检查修改参数
启动前分别检查修改runbroker.sh和runserver.sh两个文件中的JVM参数,默认的JAVA_OPT参数的值比较大,若直接启动可能会失败,需要根据实际情况重新配置
b 分别启动两个namerser节点
nohup sh bin/mqnamesrv > /dev/null 2>&1 &
查看日志
tail -f ~/logs/rocketmqlogs/namesrv.log
c 分别启动4个broker节点
maste1
nohup sh bin/mqbroker -c /usr/local/rocketmq/conf/2m-2s-async/broker-a.properties &
slave1
nohup sh bin/mqbroker -c /usr/local/rocketmq/conf/2m-2s-async/broker-a-s.properties &
maste2
nohup sh bin/mqbroker -c /usr/local/rocketmq/conf/2m-2s-async/broker-b.properties &
slave2
nohup sh bin/mqbroker -c /usr/local/rocketmq/conf/2m-2s-async/broker-b-s.properties &
查看日志:
tail -f ~/logs/rocketmqlogs/broker.log
总结:集群环境部署,主要就是以上三个步骤,需要注意的是过程中broker配置文件的配置正确性,还需要注意一下启动前对jvm参数的检查
05.rocketmq如何保证高可用性?
1)集群化部署NameServer。Broker集群会将所有的broker基本信息、topic信息以及两者之间的映射关系,轮询存储在每个NameServer中(也就是说每个NameServer存储的信息完全一样)。因此,NameServer集群化,不会因为其中的一两台服务器挂掉,而影响整个架构的消息发送与接收; 2)集群化部署多broker。producer发送消息到broker的master,若当前的master挂掉,则会自动切换到其他的master cosumer默认会访问broker的master节点获取消息,那么master节点挂了之后,该怎么办呢?它就会自动切换到同一个broker组的slave节点进行消费 那么你肯定会想到会有这样一个问题:consumer要是直接消费slave节点,那master在宕机前没有来得及把消息同步到slave节点,那这个时候,不就会出现消费者不就取不到消息的情况了? 这样,就引出了下一个措施,来保证消息的高可用性 3)设置同步复制 前面已经提到,消息发送到broker的master节点上,master需要将消息复制到slave节点上,rocketmq提供两种复制方式:同步复制和异步复制 异步复制,就是消息发送到master节点,只要master写成功,就直接向客户端返回成功,后续再异步写入slave节点 同步复制,就是等master和slave都成功写入内存之后,才会向客户端返回成功 那么,要保证高可用性,就需要将复制方式配置成同步复制,这样即使master节点挂了,slave上也有当前master的所有备份数据,那么不仅保证消费者消费到的消息是完整的,并且当master节点恢复之后,也容易恢复消息数据 在master的配置文件中直接配置brokerRole:SYNC_MASTER即可06.rocketmq的工作流程是怎样的?
RocketMq的工作流程如下: 1)首先启动NameServer。NameServer启动后监听端口,等待Broker、Producer以及Consumer连上来 2)启动Broker。启动之后,会跟所有的NameServer建立并保持一个长连接,定时发送心跳包。心跳包中包含当前Broker信息(ip、port等)、Topic信息以及Borker与Topic的映射关系 3)创建Topic。创建时需要指定该Topic要存储在哪些Broker上,也可以在发送消息时自动创建Topic 4)Producer发送消息。启动时先跟NameServer集群中的其中一台建立长连接,并从NameServer中获取当前发送的Topic所在的Broker;然后从队列列表中轮询选择一个队列,与队列所在的Broker建立长连接,进行消息的发送 5)Consumer消费消息。跟其中一台NameServer建立长连接,获取当前订阅Topic存在哪些Broker上,然后直接跟Broker建立连接通道,进行消息的消费07.RocketMq使用哪种方式消费消息,pull还是push?
RocketMq提供两种方式:pull和push进行消息的消费 而RocketMq的push方式,本质上也是采用pull的方式进行实现的。也就是说这两种方式本质上都是采用consumer轮询从broker拉取消息的 push方式里,consumer把轮询过程封装了一层,并注册了MessageListener监听器。当轮询取到消息后,便唤醒MessageListener的consumeMessage()来消费,对用户而言,感觉好像消息是被推送过来的 其实想想,消息统一都发到了broker,而broker又不会主动去push消息,那么消息肯定都是需要消费者主动去拉的喽~08.RocketMq如何负载均衡?
1)producer发送消息的负载均衡:默认会轮询向Topic的所有queue发送消息,以达到消息平均落到不同的queue上;而由于queue可以落在不同的broker上,就可以发到不同broker上(当然也可以指定发送到某个特定的queue上) 2)consumer订阅消息的负载均衡:假设有5个队列,两个消费者,则第一个消费者消费3个队列,第二个则消费2个队列,以达到平均消费的效果。而需要注意的是,当consumer的数量大于队列的数量的话,根据rocketMq的机制,多出来的队列不会去消费数据,因此建议consumer的数量小于或者等于queue的数量,避免不必要的浪费09.RocketMq的存储机制了解吗?
RocketMq采用文件系统进行消息的存储,相对于ActiveMq采用关系型数据库进行存储的方式就更直接,性能更高了 RocketMq与Kafka在写消息与发送消息上,继续沿用了Kafka的这两个方面:顺序写和零拷贝 1)顺序写 我们知道,操作系统每次从磁盘读写数据的时候,都需要找到数据在磁盘上的地址,再进行读写。而如果是机械硬盘,寻址需要的时间往往会比较长 而一般来说,如果把数据存储在内存上面,少了寻址的过程,性能会好很多;但Kafka 的数据存储在磁盘上面,依然性能很好,这是为什么呢? 这是因为,Kafka采用的是顺序写,直接追加数据到末尾。实际上,磁盘顺序写的性能极高,在磁盘个数一定,转数一定的情况下,基本和内存速度一致 因此,磁盘的顺序写这一机制,极大地保证了Kafka本身的性能 2)零拷贝 比如:读取文件,再用socket发送出去这一过程buffer = File.read
Socket.send(buffer)
传统方式实现:先读取、再发送,实际会经过以下四次复制 1、将磁盘文件,读取到操作系统内核缓冲区Read Buffer
10.RocketMq的存储结构是怎样的?
如图所示,消息生产者发送消息到broker,都是会按照顺序存储在CommitLog文件中,每个commitLog文件的大小为1G CommitLog-存储所有的消息元数据,包括Topic、QueueId以及message CosumerQueue-消费逻辑队列:存储消息在CommitLog的offset IndexFile-索引文件:存储消息的key和时间戳等信息,使得RocketMq可以采用key和时间区间来查询消息 也就是说,rocketMq将消息均存储在 CommitLog 中,并分别提供了CosumerQueue和IndexFile两个索引,来快速检索消息11.RocketMq如何进行消息的去重?
我们知道,只要通过网络交换数据,就无法避免因为网络不可靠而造成的消息重复这个问题。比如说RocketMq中,当consumer消费完消息后,因为网络问题未及时发送ack到broker,broker就不会删掉当前已经消费过的消息,那么,该消息将会被重复投递给消费者去消费 虽然rocketMq保证了同一个消费组只能消费一次,但会被不同的消费组重复消费,因此这种重复消费的情况不可避免 RocketMq本身并不保证消息不重复,这样肯定会因为每次的判断,导致性能打折扣,所以它将去重操作直接放在了消费端:1)消费端处理消息的业务逻辑保持幂等性。那么不管来多少条重复消息,可以实现处理的结果都一样
2)还可以建立一张日志表,使用消息主键作为表的主键,在处理消息前,先insert表,再做消息处理。这样可以避免消息重复消费
12.RocketMq性能比较高的原因?
就是前面在文件存储机制中所提到的:RocketMq采用文件系统存储消息,采用顺序写的方式写入消息,使用零拷贝发送消息,这三者的结合极大地保证了RocketMq的性能三 总结
总而言之
本次文章通过12个常见的RocketMq经典面试题,带大家再次重新学习了RocketMq,相信大家对RocketMq掌握得更深入一些了 RocketMq作为扛过“双十一”的消息中间件,在Kafka的基础上做了各方面的优化,由java语言编写,方便我们查看源码了解它的每个环节的实现逻辑,并针对不同的业务场景进行扩展。所以RocketMq也是被越来越多地使用了,所以无论你是技术小白,还是工作多年的开发,甚至是架构师,利用闲暇时间重新学习RocketMq还是很必要的呢~ 点个在看支持我吧,转发就更好了