2.RocketMQ中的Topic和JMS的queue有什么区别
queue 就是来源于数据结构的 FIFO 队列。而 Topic 是个抽象的概念,每个 Topic 底层对应N个 queue,而数据也真实存在 queue 上的。
3.RocketMQ Broker中的消息被消费后会立即删除吗
「不会」,每条消息都会持久化到CommitLog中,每个Consumer连接到Broker后会维持消费进度信息,当有消息消费后只是当前Consumer的消费进度(CommitLog的offset)更新了。
4.6版本默认48小时后会删除不再使用的CommitLog文件
检查这个文件最后访问时间
判断是否大于过期时间
指定时间删除,默认凌晨4点
4.RocketMQ消费模式有几种
消费模型由 Consumer 决定,消费维度为 Topic。
集群消费
一条消息只会被同Group中的一个Consumer消费
多个Group同时消费一个Topic时,每个Group都会有一个Consumer消费到数据
广播消费
消息将对一 个 Consumer Group 下的各个 Consumer 实例都消费一遍。即即使这些 Consumer 属于同一个 Consumer Group ,消息也会被 Consumer Group 中的每个 Consumer 都消费一次。
5.RocketMQ消息是push还是pull
RocketMQ没有真正意义的push,都是pull,虽然有push类,但实际底层实现采用的是「长轮询机制」,即拉取方式
broker端属性 longPollingEnable 标记是否开启长轮询。默认开启
6.为什么要主动拉取消息而不适用事件监听方式
事件驱动方式是建立好长连接,由事件(发送数据)的方式来实时推送
如果Broker主动推送消息的话可能push速度快,消费速度慢的情况,那么就会造成消息在Consumer端堆积过多,同时又不能被其他consumer消费的情况。而pull的方式可以根据当前自身情况来pull,不会造成
过多的压力而造成瓶颈。所以采用pull方式.
7. Broker如何处理拉去请求的
Consumer首先请求Broker Broker是否有符合条件的消息
有:相应Consumer 等待下次Consumer的请求
没有:
DefaultMessageStore#ReputMessageService#run方法
PullRequesetHoldService来hold连接,每个5s执行一次检查pullRequestTable有没有消息,有点话立即推送每隔1ms检查commitLog中是否有新消息,有的话写入到pullRequestTable
当有新消息的返回请求
挂起consumer的请求,即不断开连接,也不返回数据
使用consumer的offset
8.RocketMQ如何做负载均衡
通过Topic再多个Broker中分布式存储实现
1.producer端
发送端指定message queue发送消息到相应的broker,来达到写入时的负载均衡
a.提升写入吞吐量,当多个producer同时向一个broker写入数据的时候,性能会下降
b.消息分布在多个broker中,为负载消费做准备
默认策略是随机选择
producer维护一个index
每次取节点会自增
index向所有broker个数取余
自带容错策略
2.consumer端
采用的是平均分配算法来进行负载均衡
3.其他负载均衡算法
平均分配策略
环形分配策略
手动配置分配策略
机房分配策略
一致性哈希分配策略
靠近机房分配策略
9.Topic创建的模式
手动创建:
1.集群模式:当前模式下,Broker中Queue数量相等
2.Broker模式:当前模式下,Broker的的queue可以不一样
自动创建topic的时候,默认是Broker模式,会为每一个Broker创建4个Queue
10.读写队列问题
从物理上看,读写队列是相同队列,所以不会出现读写队列数据同步问题
从逻辑上看,分为读写队列,一般数量是相等的
例如:创建Topic的时候,读队列为4个,写队列为8个,那么系统会创建8个队列,0-7,可读队列为0-3 Producer会将消息写入0-7的Queue,Consuemr会消费0-3的队列
创建topic的时候,读队列为8个,写队列为4个,那么系统会创建8个队列,0-7,可读的队列为0-7 procuer会将消息写入0-3的Queue,Consuemer会消费0-7的Queue,不过4-7的Queue无数据
假设Consumer1消费0-3,Consuemer2消费4-7,那么Consuemer2没有消息消费
11.当消费负载均衡consumer和queue不对等的时候会发生什么
Consumer和Queue会优先平均分配,如果Consuemr少于queue的个数,则会存在部分Consummer消费多个queue的情况。如果Consumer等于queue的个数,那么就是一个consumer消费一个queue,如果Consumer个数大于queue的个数,那么会有部分Consumer空余出来,白白的浪费了
12.消息重复消费如何解决?
影响正常发送和消费的【重要原因是网络不确定性】
【引起重复消费的原因】
【ACK】正常情况下在consumer真正消费完消息后应该发送ACK,通知broker该该消息已正常消费,从queue中剔除。当ack因为网络原因无法发送到broker,broker会认为词条消息没有被消费,此后会开启消息重头机制把消息再次投递到consumer
【消费模式】在CLUSTERING模式下,消息在broker中会保证相同group的consumer消费一次,但是针对不同group的consumer会推送多次
【解决方案】
a.数据库表 处理消息前,使用消息主键再表中带有约束字段的insert
b.Map 单机是可以使用map ConcurrentHashMap-> putlfAbsent guava cache
c.Redis
分布式锁
13.如何让RocketMQ保证消息的顺序消费
首先多个queue只能保证单个queue里的顺序,queue是典型的FIFO,天然顺序。多个queue同时消费时无法绝对保证消息的有序性。所以总结如下:
同一个topic,同一个Queue,发消息的时候一个线程去发送消息,消费的时候一个线程去消费一个queue里的消息
14.怎么保证消息发到同一个queue
RocketMQ给我们提供了MessageQueueSeletor接口,可以自己重写里面的接口,实现自己的算法,举个最简单的例子:判断i/2==0,那就放到queue1里,否则放到queue2里
15.RocketMQ如何保证消息不丢失
首先在如下三个部分都可能会出现丢失消息的情况:
Producer端
Broker端
Consumer端
1.Producer端如何保证消息不丢失
采取send()【同步消息】,发送结果是同步感知的。
发送失败后可以重试【重试】。设置重试次数,默认为3次
【集群部署】,比如发送失败了的原因可能是当前Broker宕机了,重试的时候会发送到其他Broker上。
2.Broker端如何保证消息不丢失
修改刷盘策略为同步刷盘。默认情况下是异步刷盘的。
集群部署,主从模式,高可用
3.Consumer端如何保证消息不丢失
完全消息正常后进行手动ack确认。
16.RocketMQ的消息堆积如何处理
首先找打是什么原因导致消息堆积,Producer太多了,Consuemr太少了导致的还是其他情况,总之先定位原因
然后看下消息消息速度是否正常,正常的话,可以通过上线更多的Consumer临时解决消息堆积问题
17.如果Consumer和Queue不对等,上线了多台也在短时间内无法消费完堆积的消息怎么办?
1.准备一个临时的topic
2.queue的数量是堆积的几倍
3.queue分布到多个Broker中
4.上线一台Consumer做消息的搬运工,把原来topic中的消息挪到新的Topic里,不做业务逻辑处理,只是挪过去
5.上线N台Consumer同时消费临时topic中的数据
6.改bug
7.恢复原来的Consumer,继续消费之前的topic
18.堆积消息会超时删除吗?
【不会】;RocketMQ中的消息只会在commitLog被删除的时候才会消失。也就是说未被消费的消息不会存在超过时删除这情况
19.堆积的消息会不会进入死信队列
【不会】,消息在消费失败后会进入重试队列(%RETRY%+ConsumerGroup),18次才会进入死信队列(%DLQ%+ConsumerGroup)
20.RocketMQ在分布式事务支持这块机制的底层原理
分布式系统中事务可以使用【TCC】(Try,Confirm,Cancel),【2pc】来解决分布式系统中的消息原子性
RocketMQ4.3+提供分布式事务功能,通过RocketMQ事务消息能达到分布式事务的最终一致
【RocketMQ实现方式:】
【Half message】:预处理消息,当broker收到此类消息后,会存储到RMQ_SYS_TRANS_HALF_TOPIC的消息消费队列中
【检查事务状态】:Broker会开启一个定时任务,消费RMQ_SYS_TRANS_HALF_TOPIC队列中的消息,每次执行任务会向消息发送者确认事务执行状态(提交,回滚,未知),如果是未知,Broker会定时去回调在重新检查
【超时】:如果超过回查次数,默认回滚消息
也就是他并未真正进入Topic的queue,而是用了临时queue来放所谓的half message,等提交事务后,才会真正的将half message 转移到topic下的queue。
21.高吞吐量下如何优化生产者和消费者的性能
开发
消息批量拉去,业务逻辑批量处理,同一个group下,多机部署,并行消费,单个Consumer提高线程个数,批量消费
运维
网卡调优,jvm调优,多线程与cpu调优,Page Cache
22.RocketMQ是如何保证数据的高容错性的
在不开启容错的情况下,轮询队列进行发送,如果失败了,重试的时候过滤失败的Broker
如果开启了容错策略,会通过RocketMQ的预测机制来预测一个Broker是否可用
如果上次失败了的Broker可用那么还是会选择该Broker的队列
如果上述情况失败,则随机选择一个进行发送
在发送消息的时候会记录一下调用的时间与是否报错,根据该时间去预测broker的可用时间
23.任何一台Broker突然宕机了怎么办?
Broker主从架构以及多副本策略。Master收到消息后会同步Slave,这样一条消息就不止一份了,Master宕机了还有slave中消息可用,保证了MQ的可靠性和高可用性。而且RocketMQ4.5.0开始支持Dlegder模式,基于raft的,做了真正意义的HA.
24.Broker把自己的信息注册到哪个NameServer上?
每个Broker会向所以的NameServer上注册自己的信息。即每个NameServer上有所有的Broker信息
25.RocketMQ如何分布式存储海量消息的
Rocketmq进程一般称为Broker,集群部署的各个Broker收到不同的消息,然后存储再自己本地的磁盘文件中
26.任何一台Broker突然宕机了怎么办?还能使用吗?消息会不会丢
RocketMQ的解决思路是Broker主从架构以及多副本策略。
Master收到消息后会同步给slave,这样一条消息不止一份了,Master宕机了还有slave中消息可用,保证了MQ的可靠性和高可用性
27.怎么知道有哪些Broker?如何知道连接那个broker?
有个NameServer的概念,是独立部署在几台机器上的,然后所有的Broker都会把自己注册到NameServer上去,NameServer就知道集群有哪些Broker
发送消息到Broker,会找到NameServer去获取路由信息,系统要从Broker获取信息,也会找NameServer获取路由信息,去找到对应的Broker获取消息
28.NameServer到底可以部署几台机器?为什么要集群化部署?
部署多台,保证高可用性。
集群化部署是为了高可用性,NameServer是集群里非常关键的一个角色,如果部署一台NameServer,宕机会导致RocketMQ集群出现故障,所以NameServer一定会多机器部署,实现一个集群,起到高可用的效果
29.系统如何从NameServer获取Broker信息?
系统主动去NameServer上拉去Broker信息及其他相关信息
30.如果Broker宕了,NameServer是怎么感知的?
Broker会定时(30s)向NameServer发送心跳,然后NameServer会定时(10s)运行一个任务,去检查一下各个Broker的最近一次心跳时间,如果某个Broker超过120s都没发送心跳,那么就会认为这Broker已经挂掉了
31.Broker挂了,系统怎么感知的?
主要是通过拉去NameServer上Broker的信息。但是,因为Broker心跳,NameServer定时任务,生产者和消费者拉去Broker信息,这些操作都是周期性的,所以不会实时感知,所以存在发送消息和消费消息失败的情况,
对于生产者而言,他是有一套容错机制的
32.Master Broker 是如何将消息同步给Slave Broker的?
RocketMQ自身的Master-Slave 模式采取Pull模式拉取消息.
33.消费消息时是从Master获取还是Slave获取?
可能从Master Broker获取也可能从slave获取消息
a.消费者的系统在获取消息的时候会先发送请求到Master Broker上去,请求获取一批消息,此时Master Broke是返回一批消息给消费者系统的
b.Master Broker 在返回消息给消费者系统的时候,会根据当时Master Broker的负载情况和slave Broker 的同步情况,向消费者系统建议下一次拉去消息的时候是从Master Broker 拉取还是从Slave Broker拉取
34.如果Slave Broker 挂掉了,会对整个系统有影响吗?
有一点影响,但是影响不太大,因为消息写入全部是发送到Master Broker的,获取消息也可以master获取,少了Slave Broker ,会导致所以读写压力集中在Master Broker
35.Master Broker 突然挂了,这样会怎么样?
[RocketMQ4.5版本之前],用slave Broker 同步数据,尽量保证数据不丢失,但是一旦Master故障了,Slave是没发自动切换成Master的,所以在这种情况下,如果Master Broker宕机了,这时就得手动做一些运维操作,
把Slave Broker 重新配置修改一些配置,重启机器给调整为Master Broker 这是有点麻烦,而且会导致中间一段时间不可用
【RocketMQ4.5之后】支持了一种叫做Dledger机制,基于Raft协议实现了一个机制,我们可以让一个Master Broker对应多个Slave Broker,一旦Master Broker宕机了,在多个Slave中通过Dledger技术将一个Slave Broker选为新的Master Broker对外
提供服务。在生产环境中可以是用Dledger机制实现自动故障切换,只要10s或者几十秒的时间就可以完成