RabbitMQ 常见面试题 不看你就亏了

RabbitMQ的使用场景

①顺序消费 

②定时任务

③请求削峰

④异步通信

                                 

RabbitMQ基本概念 

Broker: 消息队列服务器实体 

Exchange: 消息交换机,它指定消息按特定规则,路由到哪个队列 

Queue: 消息队列载体,每个消息都会被投入到一个或多个队列 

Binding: 绑定,它的作用就是把exchange和queue按照路由规则绑定起来

Routing Key: 路由关键字,exchange根据这个关键字进行消息投递 

VHost: vhost 可以理解为虚拟 broker ,即 mini-RabbitMQ server。其内部均含有独立的 queue、exchange 和 binding 等,拥有独立的权限系统,可以做到 vhost 范围的用户控制。 

Producer: 消息生产者,

Consumer: 消息消费者

Channel: 消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务 

  

MQ 有哪些常见问题?

消息的顺序问题

假如生产者产生了 2 条消息:P1、P2,要求P1 发送到 M1,P2 发送到 M2,如果要保证 P1 先于 P2 被消费,怎么做?

解决方案:

保证生产者 - MQServer - 消费者是一对一对一的关系

缺陷:  

 ①如果消费端发生出现阻塞 就要花费大量精力解决问题。 

 ②吞吐量不够就会成为消息系统的瓶颈 

                                  

RabbitMQ的工作模式

simple模式

1.消息产生消息,将消息放入队列 

2.消息的消费者 监听 消息队列,如果队列中有消息,就消费掉,消息被拿走后,自动从队列中删除

work工作模式

1.消息产生者将消息放入队列消费者可以有多个,消费者1,消费者2同时监听同一个队列,消息被消费。消费者1,消费者2共同争抢当前的消息队列内容,谁先拿到谁负责消费消息

缺陷:高并发下 不能保证消息只被一个队列消费 可以加锁控制

publish/subscribe发布订阅模式

1.每个消费者监听自己的队列;

2.生产者将消息发给消息队列服务器实体 ,由交换机将消息转发到绑定此交换机的每个队列,每个绑定交换机的队列都将接收到消息。

routing路由模式

1.消息生产者将消息发送给交换机按照路由判断,路由是字符串(业务功能定义路由字符串 ) 当前产生的消息携带路由字符(对象的方法),交换机根据路由的key,只能匹配上路由key对应的消息队列,对应的消费者才能消费消息; 

2.从系统的代码逻辑中获取对应的功能字符串,将消息任务扔到对应的队列中。

topic主题模式

1.生产者发送消息到交换机;

2.交换机消息送达队列为topic方式;

3.消费者模糊匹配路由Key,进行消息消费;

# 匹配一个或多个

* 匹配一个

一般使用#号匹配多个,*号用的比较少。

                                                                        

消息基于什么传输?

RabbitMQ 使用信道的方式来传输数据。(由于 TCP 连接的创建和销毁开销较大,且并发数受系统资源限制,会造成性能瓶颈。)信道是建立在真实的 TCP 连接内的虚拟连接,且每条 TCP 连接上的信道数量没有限制。

如何保证RabbitMQ消息的可靠传输?

消息不可靠的情况可能是消息丢失,劫持等原因

丢失又分为:

生产者丢失消息消息列表丢失消息消费者丢失消息

① 生产者丢失消息:从生产者弄丢数据这个角度来看,

RabbitMQ提供transaction机制confirm模式来确保生产者不丢消息;

 transaction机制就是说:发送消息前,开启事务(channel.txSelect()),然后发送消息,如果发送过程中出现什么异常,事务就会回滚(channel.txRollback()),如果发送成功则提交事务(channel.txCommit())。

 confirm模式用的居多:一旦channel进入confirm模式,所有在该信道上发布的消息都将会被指派一个唯一的ID(从1开始),一旦消息被投递到所有匹配的队列之后;  RabbitMQ就会发送一个ACK给生产者(包含消息的唯一ID),这就使得生产者知道消息已经正确到达目的队列了;

 如果RabbitMQ没能处理该消息,则会发送一个Nack消息给你,你可以进行重试操作。

 ②消息队列丢数据:消息持久化。 

 处理消息队列丢数据的情况,一般是开启持久化磁盘的配置

 将队列的持久化标识durable设置为true,则代表是一个持久的队列 发送消息的时候将 deliveryMode=2 这样设置以后,即使RabbitMQ挂了,重启后也能恢复数据  

③消费者丢失消息:消费者丢数据一般是因为采用了自动确认消息模式,改为手动确认消息 

消费者在收到消息之后,处理消息之前,会自动回复RabbitMQ已收到消息; 如果这时处理消息失败,就会丢失该消息;

 解决方案:处理消息成功后,手动回复确认消息。 

如何确保消息正确地发送至 RabbitMQ? 如何确保消息接收方消费了消息? 

发送方确认模式 

将信道设置成 confirm 模式(发送方确认模式),则所有在信道上发布的消息都会被指派一个唯一的 ID。  

一旦消息被投递到目的队列后,或者消息被写入磁盘后(可持久化的消息),信道会发送一个确认给生产者(包含消息唯一 ID)。 如果 RabbitMQ 发生内部错误从而导致消息丢失,会发送一条 nack(notacknowledged,未确认)消息。

 发送方确认模式是异步的,生产者应用程序在等待确认的同时,可以继续发送消息。当确认消息到达生产者应用程序,生产者应用程序的回调方法就会被触发来处理确认消息。

接收方确认机制 

消费者接收每一条消息后都必须进行确认(消息接收和消息确认是两个不同操作)。只有消费者确认了消息,RabbitMQ 才能安全地把消息从队列中删除。 这里并没有用到超时机制,RabbitMQ 仅通过 Consumer 的连接中断来确认是否需要重新发送消息。也就是说,只要连接不中断,RabbitMQ 给了 Consumer 足够长的时间来处理消息。保证数据的最终一致性。 

                                                               

死信队列和延迟队列的使用?

死信消息:

消息被拒绝(Basic.Reject或Basic.Nack)并且设置 requeue 参数的值为 false
消息过期了
队列达到最大的长度

过期消息:

在 rabbitmq 中存在2种方可设置消息的过期时间,第一种通过对队列进行设置,这种设置后,该队列中所有的消息都存在相同的过期时间,第二种通过对消息本身进行设置,那么每条消息的过期时间都不一样。如果同时使用这2种方法,那么以过期时间小的那个数值为准。当消息达到过期时间还没有被消费,那么那个消息就成为了一个 死信 消息。

队列设置:在队列申明的时候使用 x-message-ttl 参数,单位为 毫秒

单个消息设置:是设置消息属性的 expiration 参数的值,单位为 毫秒

延时队列:在rabbitmq中不存在延时队列,但是我们可以通过设置消息的过期时间和死信队列来模拟出延时队列。消费者监听死信交换器绑定的队列,而不要监听消息发送的队列。

RabbitMQ的部署模式

普通模式:默认模式,以两个节点(rabbit01,rabbit02)为例来进行说明,对于Queue来说,消息实体只存在于其中一个节点rabbit01(或者rabbit02),rabbit01和rabbit02两个节点仅有相同的元数据,即队列结构。当消息进入rabbit01节点的Queue后,consumer从rabbit02节点消费时,RabbitMQ会临时在rabbit01,rabbit02间进行消息传输,把A中的消息实体取出并经过B发送给consumer,所以consumer应尽量连接每一个节点,从中取消息。即对于同一个逻辑队列,要在多个节点建立物理Queue。否则无论consumer连rabbit01或rabbit02,出口总在rabbit01,会产生瓶颈。当rabbit01节点故障后,rabbit02节点无法取到rabbit01节点中还未消费的消息实体。如果做了消息持久化,那么等到rabbit01节点恢复,然后才可被消费。如果没有消息持久化,就会产生消息丢失的现象。

镜像模式:把需要的队列做成镜像队列,存在与多个节点属于RabibitMQ的HA方案,该模式解决了普通模式中的问题,其实质和普通模式不同之处在于,消息体会主动在镜像节点间同步,而不是在客户端取数据时临时拉取,该模式带来的副作用也很明显,除了降低系统性能外,如果镜像队列数量过多,加之大量的消息进入,集群内部的网络带宽将会被这种同步通讯大大消耗掉,所以在对可靠性要求比较高的场合中适用

节点分为内存节点(保存状态到内存,但持久化的队列和消息还是会保存到磁盘),磁盘节点(保存状态到内存和磁盘),一个集群中至少需要一个磁盘节点

RabbitMQ的缺点 

系统可用性降低 

系统引入的外部依赖越多,越容易挂掉,本来你就是A系统调用BCD三个系统的接口就好了,人ABCD四个系统好好的,没啥问题,你偏加个MQ进来,万一MQ挂了咋整?MQ挂了,系统崩了 哭了。

系统复杂性提高 

硬生生加个MQ进来,你怎么保证消息没有重复消费?怎么处理消息丢失的情况?怎么保证消息传递的顺序性?溜了溜了

一致性问题

 A系统处理完了直接返回成功了,人都以为你这个请求就成功了;但是问题是,要是BCD三个系统那里,BD两个系统写库成功了,结果C系统写库失败了 啊 人麻了

                                

ActiveMQ、RabbitMQ、RocketMQ 有什么优缺点?

好了 就到这了 再问打死

                                                   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

音阙斯听

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值