主题
消息中间件MQ
1.为什么使用MQ?MQ的优点消息队列有什么优缺点?
- 解耦:系统耦合度降低,没有强依赖关系
- 异步:不需要同步执行的远程调用可以有效提高响应时间
- 削峰:请求达到峰值后,后端service还可以保持固定消费速率消费,不会被压垮
2.RabbitMQ有什么优缺点?
优点:和上述一致 1.异步处理 2.削峰 3.解耦
缺点:
- 系统可用性降低
- 系统复杂度提高 :加入了消息队列,要多考虑很多方面的问题,比如:一致性问题、如何保证消息不被重复消费、如何保证消息可靠性传输等。因此,需要考虑的东西更多,复杂性增大。
- 一致性问题:A系统处理完业务,通过消息队列发送给B、C系统进行后续业务处理,如果B系统处理成功,C系统处理失败的情况。
3.Kafka、ActiveMQ、RabbitMQ、RocketMQ 有什么优缺点?
| 特性 | ActiveMQ | RabbitMQ | RocketMQ | Kafka |
|---|---|---|---|---|
| 单机吞吐量 | 万级,比RocketMQ和Kafka低一个数量级 | 同ActiveMQ | 十万级,支撑高吞吐量 | 十万级,高吞吐量,适合海量数据采集、日志采集等,适合高并发应用 |
| 开发语言 | java | erlang | java | scala |
| topic数量对吞吐量的影响 | topic 可以达到几百/几千的级别,吞吐量会有较小幅度的下降,这是RocketMQ的一大优势,在同等机器下可以支撑大量的topic | topic 从几十到几百个时候,吞吐量会大幅度下降,在同等机器下,Kafka 尽量保证 topic 数量不要过多,如果要支持大规模的topic,需要增加更多的机器来支持 | ||
| 时效性 | ms级 | 微秒,这是rabbitMQ的一点特性,延迟最低 | ms级 | 延迟在ms级以内 |
| 可用性 | 高,基于主从架构实现高可用 | 同ActiveMQ | 非常高,基于分布式架构实现高可用 | 非常高,基于分布式,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用 |
| 消息可靠性 | 有较低的概率丢失数据 | 基本不丢 | 经过参数优化配置,可以做到0丢失 | 同RocketMQ |
| 功能支持 | MQ领域的功能极其完备 | 基于Erlang开发,并发能力强,性能极其好,延时很低 | MQ功能较为完善,还是分布式的,扩展性好 | 功能较为简单,主要支持简单的MQ功能,在大数据领域的实时计算以及日志采集被大规模使用 |
| 社区活跃度 | 低 | 很高 | 一般 | 很高 |
4.MQ 有哪些常见问题?如何解决这些问题?
MQ常见的问题:
消息的顺序问题:
消息有序指的是可以按照消息的发送顺序来消费。
假如生产者产生了 2 条消息:M1、M2,假定 M1 发送到 S1,M2 发送到S2,如果要保证 M1 先于 M2 被消费,怎么做?

解决方案:
(1).保证生产者-MQServer-消费者是一对一对一的关系

缺陷:
- 并行度就会称为消息系统的瓶颈(吞吐量不够)
- 更多的异常处理,比如:只要消费端出现问题,就会导致整个处理流程阻塞,我们不得不花费更多的精力来解决阻塞问题。(2).通过合理的设计或者将问题分解来规避。
- 不关注乱序的应用实际大量存在
- 队列无序并不意味着消息无序,所以从业务层面来保证消息的顺序而仅仅是依赖于消息系统,是一种更合理的方式。
消息的重复问题:
造成消息重复的根本原因是:网络不可达。
所以解决这个问题的办法就是绕过这个问题。那么问题就变成了:如果消费端收到两条一样的消息,应该怎样处理?
消费端处理消息的业务逻辑保持幂等性。只要保持幂等性,不管来多少条重复消息,最后处理的结果都一样。保证每条消息都有唯一编号且保证消息处理成功与去重表的日志同时出现。利用一张日志表来记录已经处理成功的消息的 ID,如果新到的消息 ID 已经在日志表中,那么就不再处理这条消息。
5.什么是RabbitMQ?
采用 AMQP 高级消息队列协议的一种消息队列技术,最大的特点就是消费并不需要确保提供方存在,实现了服务之间的高度解耦
6.rabbitmq 的使用场景
- 服务间异步通信
- 顺序消费
- 定时任务
- 请求削峰
7.RabbitMQ基本概念
8.RabbitMQ的工作模式
9.如何保证RabbitMQ消息的顺序性?
拆分多个 queue,每个 queue 一个 consumer,就是多一些 queue 而已,确实是麻烦点;或者就_一个 queue 但是对应一个 consumer,然后这个consumer 内部用内存队列做排队_,然后分发给底层不同的 worker 来处理。
10.消息如何分发?
若该队列至少有一个消费者订阅,消息将以循环(round-robin)的方式发送给消费者。每条消息指挥分发给一个订阅的消费者(前提是消费者能够正常处理消息并进行确认)。通过路由可实现多消费功能。
11.消息怎么路由?
消息提供方->路由->一至多个队列消息发布到交换器时,消息将拥有一个路由键(routing key),在消息创建时设定。通过队列路由键,可以把队列绑定到交换器上。消息到达交换器后,RabbitMQ 会将消息的路由键与队列的路由键进行匹配(针对不同的交换器有不同的路由规则);
常用的交换器主要分为一下三种:
- fanout:如果交换器收到消息,将会广播到所有绑定的队列上
- direct:如果路由键完全匹配,消息就被投递到相应的队列
- topic:可以使来自不同源头的消息能够到达同一个队列。 使用 topic 交换器时,可以使用通配符
12.消息基于什么传输?
由于_ TCP _连接的创建和销毁开销较大,且并发数受系统资源限制,会造成性能瓶颈。RabbitMQ 使用信道的方式来传输数据。信道是建立在真实的 TCP 连接内的虚拟连接,且每条 TCP 连接上的信道数量没有限制。
13.如何保证消息不被重复消费?或者说,如何保证消息消费时的幂等性?
14.如何确保消息正确地发送至 RabbitMQ? 如何确保消息接收方消费了消息?
15.如何保证RabbitMQ消息的可靠传输?
16.为什么不应该对所有的 message 都使用持久化机制?
17.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即可