11.RabbitMQ面试题

1.Rabbitmq基本概念

Rabbitmq是一款开源的,Erlang编写的,基于AMQP协议的消息中间件
Broker(Server): 简单来说就是消息队列服务器实体
Message: 服务与应用程序之间传递的数据
Exchange: 交换机,它指定消息按什么规则,路由到哪个队列
Routing key:路由关键字,exchange根据这个关键字进行消息投递
Queue: 消息队列载体,每个消息都会被投入到一个或多个队列
Binding: 绑定,它的作用就是把exchange和queue按照路由规则绑定起来
Channel: 消息读写的通道,客户端可以建立多个 channel,每个channel代表一个会话任务
Connection:应用程序与Broker的网络连接,TCP/IP 三次握手和四次挥手。
VHost: 可以理解为虚拟的broker
Producer: 消息生产者
Consumer: 消息消费者

2.为什么要使用Rabbitmq?

解耦:例如,A系统产生一条数据发送到MQ里面,哪个系统需要数据自己去MQ里面消费。新系统需要数据直接从MQ里消费即可,如果系统不需要这条数据,就取消对MQ的消费。这样下来,A系统压根就不需要去考虑给谁发送数据,不需要维护复杂的代码。
异步:将消息写入消息队列,能够让非必要的业务逻辑以异步的方式运行,加快响应速度。
削峰: 减少高峰期对服务器的压力

3.消息怎么路由?交换机有哪几种?

消息创建时可以设定一个路由键,队列也绑定到交换机时也可以创建路由键。
当消息到达交换机时,RabbitMQ会将消息的路由键与队列的路由键进行匹配。如果能够匹配到队列,则消息会投递到相应的队列中,如果不能匹配到任何队列,消息将进入黑洞。

不同的交换机有不同的路由规则,常用的交换机主要由以下三种:
fanout: 如果交换机收到消息,跟它绑定的队列都能收到消息。fanout交换机去指定路由key是毫无意义的
direct: 如果路由键完全匹配,消息才会投递到相应的队列上
topic: 使用topic交换机,队列的路由键可以使用通配符。可以使路由键不同的消息都能够到达同一队列
比如:"*"是匹配特定位置的任意文本 “#”是匹配所有规则 "."是把路由器分为了几部分

4.Rabbitmq的工作模式

简单模式Simple:消息生产者将消息放入队列,消费者监听队列,如果有消息就消费掉,消息被拿走后,自动从队列中删除。
在这里插入图片描述
工作模式Work:消息生产者将消息放入队列。队列被多个消费者监听。那消息会被哪个消费者监听,有两种模式。
1.轮询模式(Round-Robin):一个消费者一条,按均分配
2.公平分发(Fair Dispatch):根据消费者的消费能力公平分发,处理快的消费的多,处理慢的消费的少,按劳分配
在这里插入图片描述
发布订阅模式Publish/Subscribe
1.发布订阅模式是一种广播机制,它是没有路由key的模式。
2.生产者将消息发送给Broker,交换机将消息转发到绑定此交换机的每个队列,每个队列都能接收到消息。
在这里插入图片描述
路由模式Routing:交换机只把消息发送给路由键完全匹配到的队列
在这里插入图片描述
主题模式(路由模式的一种)Topic:队列的路由键可以使用通配符,模糊的routing-key的匹配模式。路由键不同的消息可以投递到同一个队列中。
在这里插入图片描述

5.消息基于什么传输?为什么要采用这种运输?

Rabbimq采用信道的方式传输数据
1.tcp的创建和销毁,开销大,创建要三次握手,销毁要四次挥手
2.如果不用信道,那客户端就会用TCP连接到Rabbitmq服务器,高峰时每秒成千上万连接会造成资源的巨大浪费,而且底层操作系统每秒处理TCP连接数也是有限制的,必定造成性能瓶颈
3.信道的原理是一条线程一条信道,多条线程多条信道同用一条TCP连接,一条TCP连接可以容纳无限的信道,即使成千上万的请求也不会造成性能瓶颈
在这里插入图片描述

6.如何保证消息的可靠性投递

使用Rabbitmq的消息确认机制
发送端的消息确认机制
confirmCallback:当消息到达broker后就会触发confirmCallback,被broker接收到只能表示message已经到达服务器,并不能保证消息一定会被投递到目标queue里,所以需要returnsCallback
returnsCallback:如果消息到达broker后,未能投递到目标队列将触发returnsCallback(成功投递队列不触发),可以获取投递失败的详细信息。

消费端的消息确认机制
消费者收到消息,默认是自动确认的,只要消息接收到客户端就会自动确认,服务端就会移除这个消息,
但是如果无法确定此消息是否被处理完成,或者成功处理,我们可以开启手动ack模式,只要我们没有明确告诉mq这条消息处理完成,没有ack,消息就一直是unack状态,会重新变为ready状态。

  • channel.basicAck 用于肯定确认:broker 将移除此消息
  • channel.basicNack 用于否定确认:可以指定 broker 是否丢弃此消息,可以批量
  • channel.basicReject 用于否定确认,同上,但不能批量

7.如何避免消息重复投递或重复消费?

在消息生产时,MQ内部针对每条生产者发送的消息会生成一个 inner-msg-id,作为去重和幂等的依据。避免重复的消息进入队列;
在消息消费时,要求消息体中必须有一个全局唯一ID(对于同一业务全局唯一,如支付ID、订单ID)作为去重和幂等的依据,避免同一条消息被重复消费
具体做法:
1.将业务逻辑方法设计成幂等性的。
(如何保证消息的幂等性?让每个消息携带一个全局的唯一ID,即可保证消息的幂等性)
(1)消费者获取到消息后先根据id去查询redis/mysql是否存在该消息
(2)如果不存在,则正常消费,消费完毕后写入redis/mysql
(3)如果存在,则证明消息被消费过,直接丢弃
2.也可以使用防重表,每一个消息由于都有一个唯一的id,只要它被处理过了,就可以去防重表里面记录一下。

8.消息在什么时候会变成死信?

一个消息在满足如下条件下,会进死信路由,记住这里是路由不是队列,一个路由可以对应很多队列,(什么是死信)

  • 一个消息被Consumer拒收了,并且reject方法的参数里requeue是false。也就是说不被再次放在队列里,被其他消费者使用。(basic.reject/ basic.nack)
  • 消息的TTL到了,消息过期了。
  • 队列的长度限制满了。排在前面的消息会被丢弃或者扔到死信路由上

9.设置过期消息有哪两种方法

在rabbitmq中存在2种方法设置消息的过期时间。
第一种是通过队列属性设置,队列中所有消息都有相同的过期时间。队列申明的时候设置x-message-ttl参数,单位毫秒。
第二种是对消息进行单独设置,每条消息的TTL可以不同。设置消息的expiration参数的值,单位毫秒.
如果上述两种方法同时使用,则消息的过期时间以两者之间TTL较小的为准。消息在队列生存的时间一旦超过设置的TTL值,就称为死信消息被投递到死信队列,消费者将无法再收到该消息。对消息单独设置的过期消息,不会投递到死信队列会直接移除。
在这里插入图片描述

10.延时队列怎么使用?

Rabbitmq并没有延时队列,我们可以通过设置消息的过期时间和死信队列实现一个延时队列。
给一个队列设置消息的过期时间,死信交换机,死信路由键。当投递到这个队列的消息过期时就会把消息发送到死信交换机,这个死信交换机绑定又会把此消息投递到死信队列。消费者监听这个死信队列就可以定时的收到消息。
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值