0


RabbitMq高级面试题

*1.RabbitMQ消息*堆积问题

  1. 增加消费者:可以通过增加消费者来提高消费速度,减少消息堆积。可以通过启动多消费者实例,或者增加消费者的处理能力。
  2. 提高消费者的处理能力:可以通过优化消费者代码,提高消息的处理速度。可以使用多线程或者异步处理来提高消费者的处理能力。
  3. 增加队列的大小:可以通过增加队列的大小来减少堆积问题。但是需要注意,如果队列过大,可能会占用过多的内存空间。
  4. 设置消费者的最大消息数:可以通过设置消费者的最大消息数,当消息堆积达到一定数量时,停止接收新消息,直到已接收消息的数量减少到一定程度再继续接收新消息。
  5. 设置消息的过期时间:可以给消息设置过期时间,当消息堆积达到一定时间后,过期的消息会被自动删除,从而减少堆积问题。
  6. 使用消息确认机制:RabbitMQ提供了消息确认机制,可以确保消息被成功消费后再删除,避免消息丢失或重复消费的问题。
  7. 监控和调优:通过监控RabbitMQ的指标和指标数据,可以及时发现堆积问题并进行调优,包括调整消费者数量、消费者处理能力、队列大小等参数。

总结:需要根据具体的业务场景和需求选择合适的解决方法,或者结合多种方法来解决RabbitMQ堆积问题。

2.事务处理

3.RabbitMQ如何确保消息的不丢失?

1.生产者发送消息时可能因为网络问题导致消息没有到达交换机

RabbitMQ提供了publisher confirm机制,生产者发送消息后,可以编写ConfirmCallback函数,消息成功到达交换机后,RabbitMQ会调用ConfirmCallback通知消息的发送者,返回ACK消息,如果未到达交换机,RabbitMQ也会调用ConfirmCallback通知消息的发送者,返回NACK消息超时未发送成功也会抛出异常

2.消息到达交换机后,如果未能到达队列,也会导致消息丢失:

RabbitMQ提供了publisher return机制,生产者可以定义ReturnCallback函数,消息到达交换机,未到达队列,RabbitMQ会调用ReturnCallback通知发送者,告知失败原因

3.消息到达队列后,MQ宕机也可能导致丢失消息:

RabbitMQ提供了持久化功能,集群的主从备份功能,消息持久化,RabbitMQ会将交换机、队列、消息持久化到磁盘,宕机重启可以恢复消息。

镜像集群,仲裁队列,都可以提供主从备份功能,主节点宕机,从节点会自动切换为主,数据依然在

4.消息投递给消费者后,如果消费者处理不当,也可能导致消息丢失

SpringAMQP基于RabbitMQ提供了消费者确认机制、消费者重试机制,消费者失败处理策略:

消费者确认机制:

消费者处理消息成功,未出现异常时,Spring返回ACK给RabbitMQ,消息才被移除,消费者处理消息失败,抛出异常,宕机,Spring返回NACK或者不返回结果,消息不被移除。

消费者重试机制:

默认情况下,消费者处理失败时,消息会再次回到MQ队列,然后投递给其它消费者。Spring提供的消费者重试机制,则是在处理失败后不返回NACK,而是直接在消费者本地重试。多次重试都失败后,则按照消费者失败处理策略来处理消息。避免了消息频繁入队带来的额外压力。

消费者失败策略:

当消费者多次本地重试失败时,消息默认会丢弃。

Spring提供了Republish策略,在多次重试都失败,耗尽重试次数后,将消息重新投递给指定的异常交换机,并且会携带上异常栈信息,帮助定位问题。

4.如何防止MQ消息被重复消费?

消息重复消费的原因多种多样,不可避免。所以只能从消费者端入手,只要能保证消息处理的幂等性就可以确保消息不被重复消费。

而幂等性的保证又有很多方案:

  1. 给每一条消息都添加一个唯一id,在本地记录消息表及消息状态,处理消息时基于数据库表的id唯一性做判断。
  2. 消息去重使用乐观锁,同样是记录消息表,利用消息状态字段实现基于乐观锁的判断,保证幂等
  3. 让生产者发送消息时,每条消息加一个全局的唯一id,然后消费时,将该id保存到redis里面。消费时先去redis里面查一下是否存在,没有再去消费
  4. 基于业务本身的幂等性。比如根据id的删除、查询业务天生幂等;新增、修改等业务可以考虑基于数据库id唯一性、或者乐观锁机制确保幂等。本质与消息表方案类似。
  5. 设置消息的过期时间,可以为消息设置一个过期时间,在消费者消费消息时,先判断消息是否已经过期,如果已经过期,则不进行消费。
  6. 消费者手动确认消息,在消费者消费消息后,通过调用basic.ack()方法手动确认消息已被消费。这样一来,RabbitMQ就会从队列中删除该消息,防止消息被重复消费。

5.如何保证RabbitMQ的高可用?

要实现RabbitMQ的高可用无外乎下面两点:

做好交换机、队列、消息的持久化

搭建RabbitMQ的集群,做好主从备份,当然也可以使用仲裁队列代替镜像集群。

6.使用MQ可以解决那些问题?

RabbitMQ能解决的问题很多,例如:

解耦:将几个业务关联的微服务调用修改为基于MQ的异步通知,可以解除微服务之间的业务耦合。同时还提高了业务性能。

流量削峰:将突发的业务请求放入MQ中,作为缓冲区。后端的业务根据自己的处理能力从MQ中获取消息,逐个处理任务。流量曲线变的平滑很多。

延迟队列:基于RabbitMQ的死信队列或者DelayExchange插件,可以实现消息发送后,延迟接收的效果。

7.RabbitMQ基本概念

Broker:

简单来说就是消息队列服务器实体

Exchange:

消息交换机,它指定消息按什么规则,路由到哪个队列

Queue:

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

Binding:

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

Routing Key:

路由关键字,exchange根据这个关键字将消息投递到指定队列

******VHost: ******

vhost 可以理解为虚拟 broker ,即 mini-RabbitMQ server。其内部均含有独立的 queue、exchange 和 binding 等,但最最重要的是,其拥有独立的权限系统,可以做到 vhost 范围的用户控制。当然,从 RabbitMQ 的全局角度,vhost 可以作为不同权限隔离的手段(一个典型的例子就是不同的应用可以跑在不同的 vhost 中)。

******Producer: ******

消息生产者,就是投递消息的程序

******Consumer: ******

消息消费者,就是接受消息的程序

Channel:

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

由Exchange、Queue、RoutingKey三个才能决定一个从Exchange到Queue的唯一的线路。

**8.**如何保证 RabbitMQ 消息的顺序性?

单个队列:将需要保持顺序的消息发送到同一个队列中,这样消息会被按照发送的顺序依次处理。消费者在处理消息时,确保按照接收到的顺序进行处理。

消费者限制:为了保证消息的顺序性,可以将队列中的消费者数量限制为1个,这样同一时刻只有一个消费者能够处理消息,保证处理顺序。

消息排序字段:在消息中添加一个排序字段,消费者在处理消息时根据该字段进行排序,保证消息的顺序性。

单线程消费保证消息的顺序性

对消息进行编号,消费者处理消息时根据编号顺序来处理

9.使用了消息队列会有什么缺点?

1.系统可用性降低:本来其他系统只要运行好好的,那你的系统就是正常的。现在你非要加个消息队列进去,那消息队列挂了,你的系统不是呵呵了。因此,系统可用性降低

2.系统复杂性增加:要多考虑很多方面的问题,比如消息一致性问题、如何保证消息不被重复消费,如何保证保证消息可靠传输。因此,需要考虑的东西更多,系统复杂性增大。

10.RabbitMQ发送消息长时间没人处理过期怎么办?

消息长时间没人处理过期了我们为了不影响正常的交换机使用,我们可以将过期的消息放到一个死信交换机中,然后这个交换机绑定一个队列就是死信队列,然后通过一个专门的消费者来处理这些过期的消息,或者是记录到一个表中,方便后期处理。

11.只有消息到达过期时间没有被消费会进入死信交换机吗,还有其他的情况吗?

消息成为死信一共有三种情况。

1:队列消息长度达到限制。

2:消费者拒收消息,并且不再将消息放入原来的队列中让他重新发送。

3:原队列存在消息过期设置,消息达到超时时间未被消费。

12.怎么定义一个死信交换机和死信队列绑定呢?

我们可以通过x-dead-letter-exchange和x-dead-letter-routing-key两个参数来配置好死信交换机的名称,和死信交换机与死信队列之间的路由键名称。

13.怎么设置过期时间,用哪些方式

TTL全称Time To Live(存活时间/过期时间),是mq中用来设置过期时间的,有两种设置过期时间的方式,一个是对单个消息设置过期时间,一个是对一个队列设置过期时间,这样的话发送到队列中的消息都遵循那个过期时间。队列设置过期时间:x-message-ttl,单位:ms(毫秒),这样的话进入队列的所有消息都遵循这个过期时间。单个消息设置过期时间:expiration,单位:ms(毫秒),这样的话只有这条消息有过期时间。如果即给单条消息设置了过期时间又给队列设置了过期时间,那样的话根据最短的那个时间来。

14.RabbitMQ延时队列怎么设计

延时队列一般就是发送消息到MQ中后,消费者不要第一时间去处理,比如我们点外卖的时候我们下单成功了,这个时候库存已经减了,但是我们还没有支付,如果我们一直不支付的话,过30分钟订单就自动取消了,然后库存又恢复了。RabbitMQ中没有提供延时队列的功能,但是我们可以使用TTL+死信队列来实现延时队列的功能。

使用场景:

  1. 新创建的店铺,如果在十天内都没有上传过商品,则自动发送消息提醒
  2. 用户注册成功后,如果三天内没有登陆则进行短信提醒
  3. 用户发起退款,如果三天内没有得到处理则通知相关运营人员
  4. 预定会议后,需要在预定的时间点前十分钟通知各个与会人员参加会议
  5. 商城订单超时未支付,取消订单
  6. 试用权限到期前十分钟提醒用户
  7. 15.使用rabbitMQ如何实现消费端限流?

进行秒杀服务时,使用MQ,让客户端下单后将下单信息放入消息队列中,然后让消费端去处理,但是有时消费端总是崩溃,需要在消费端实现限流,首先需要配置消费端手动确认消息,当我们消费端消费完消息后手动确认消息,队列就认为整个消费流程走完了,就开始下一个信息的发送了第二步,配置channel.basicQos(int prefetchSize, int prefetchCount, boolean global)方法来设置限流的配置,

prefetchSize:表示消息的大小(0的话表示不限制大小)

prefetchCount:表示消息的数量

global:true表示该通道下的所有消费者都适用这个策略,而false表示只有当前这一个消费者适用这个策略。

16.rabbitMQ的工作模式

1:简单模式

就是一个生产者一个消费者,中间通过一个队列直接连接。

2:work工作模式

就是有多个消费者消费队列里的消息,队列里的消息只能被一个消费者消费,这样多部署几个消费者,就可以缓解压力,比如过年的时候抢票,抢票成功后会给你发短信,这个时候就可以把发短信的任务放入队列里,然后有多个发短信的服务来处理队列里的任务。

3:pub/sub发布订阅模式

生产者的消息只能被一个消费者消费,不符合某些实际场景。比如:我们有一个国家气象局天气预报系统,这个时候他发送消息,其他的服务商,比如百度、网易、腾讯等公司都要从国家天气预报系统那里获取天气怎么办呢?总不能百度获取了今天的天气其他公司就获取不了天气了吧,或者让国家天气预报系统给每个服务商都发送一次消息,那样显然是很麻烦的。我们需要用到一个Exchange交换机角色来帮助我们把消息发给所有订阅我们的服务商。

4:Routing路由模式

路由模式就是交换机并不是给所有订阅他的队列发送消息了,而是根据路由键来确定应该给哪个队列发送消息,队列和交换机绑定的时候需要通过路由键,而生产者发送消息的时候也需要指定路由键,这样就可以确定给哪个队列发送消息了。

5:Topics主题模式

主题模式就相当于模糊匹配,假如我想给姓张的发送消息,那么我就可以通过主题模式给所有姓张的发送消息。

**17.**RabbitMQ 上的一个 queue 中存放的 message 是否有数量限制?

可以认为是无限制,因为限制取决于机器的内存,但是消息过多会导致处理效率的下降。

**18.**RabbitMQ 允许发送的 message 最大可达多大?

根据 AMQP 协议规定,消息体的大小由 64-bit 的值来指定,所以你就可以知道到底能发多大的数据了

19.rabbitMQ支持幂等吗

支持。在消息生产时,MQ 内部针对每条生产者发送的消息生成一个 inner-msg-id,作为去重的依据(消息投递失败并重传),避免重复的消息进入队列。

在消息消费时,要求消息体中必须要有一个 bizId(对于同一业务全局唯一,如支付 ID、订单 ID、帖子 ID 等)作为去重的依据,避免同一条消息被重复消费。

标签: java rabbitmq

本文转载自: https://blog.csdn.net/baby901019/article/details/143319320
版权归原作者 开发小牛牛 所有, 如有侵权,请联系我们删除。

“RabbitMq高级面试题”的评论:

还没有评论