教你如何应对面试中的RabbitMQ

时间:2024-03-30 10:17:37

RabbitMQ作为目前应用相当广泛的消息中间件,在微服务应用、企业级应用扮演着重要的角色,不仅是面试官较为青睐的面试题之一。也能够突出你的技术水平在哪个层次,通过问这个技术来考察你的技术功力。
如果你的简历中写有使用过RabbitMQ或其他消息中间件,那么很有可能在RabbitMQ方面的第一个问题就是:为什么要使用RabbitMQ?

面试官期望的回答:

1.RabbitMQ 的使用场景
2.使用RabbitMQ之后出现了什么问题?(也即是它的缺点)

求职者的标准回答:

为了减轻小伙伴面试的压力,提高面试成功率,我总结了一个万能模板用来回答这个问题:
第一步:先说RabbitMQ 简介

rabbitmq 是面向消息的中间件,它是采用ErLang语言开发的,要想搭建RabbitMQ服务器,必须先安装ErLang的环境。它是基于信道的方式来传输数据,信道其实是TCP连接内的虚拟主机,这样节省了TCP连接的创建和销毁的开销,大大提升了性能。

第二步:介绍它的五种工作模式

备注:这里根据自己准备的情况酌情回答,可以详细的对每一种工作模式进行介绍,也可以粗略的说一下这5种模式,总之大家不要忘记(敲黑板):前面说的这些都是铺垫,重点要与自己项目建立联系,一方面可以让面试官确信你使用过它,另一方面也可以加深自己对项目的理解。

1.简单模式
一个生产者,对应一个消费者。
流程:生产者发消息给交换机,交换机把消息给绑定的队列,消费者从队列中获取消息进行消费。
应用场景:发短信,聊天等。

2.工作模式
一个生产者,对应多个消费者,但是只能有一个消费者可以获取到消息。
流程:和简单模式类似,生产者发消息给交换机,交换机把消息给绑定的队列,多个消费者同时竞争资源,只有一个消费者可以成功获得。
应用场景:抢红包等

3.发布订阅模式
一个生产者把消息发送给交换机,交换机绑定了多个队列,消费者对应绑定队列接受消息并消费。
流程:生产者将消息发给交换机,交换机会把所有的消息都同步到所有绑定的队列上,每个队列都对应一个消费者进行接受消费。
应用场景:公众号订阅,发朋友圈等。

4.路由模式
生产者将消息(消息头带着routingkey)发给交换机,交换机根据routingkey将消息发送给对应的与绑定且routingkey相同的队列,消费者从队列中获得消息进行消费。
应用场景:消费者可以根据不同消息的特性,来进行绑定队列进行消费,可以选择性的进行获取消息。

5.topic主题模式
这个模式是通过通配符来进行匹配的。
流程:生产者发送消息到交换机,交换机根据routingkey将消息发到对应的队列中,如*.orange.*能匹配到hello.orange.hello,相对应的消费者获取消息进行消费。
应用场景:跟路由模式类似,提高了对队列的选择性。

第三步:结合项目

我们这时候要说一下自己在项目用的哪一种模式,并且在哪个地方用到了RabbitMQ用它帮助我们解决了什么问题。(这块要根据自己具体写的什么项目来决定)

第四步:为什么使用RabbitMQ

这里我们就回答它的业务场景,也即是它的优点
主要有以下三个核心业务场景:应用解耦,异步处理,流量削峰。
应用解耦:MQ相当于一个中间商,生产者通过MQ与消费者进行交互,将应用程序进行解耦合。

异步处理:将一些不需要同步的操作由消息队列通知消息接收方进行异步处理,提高了系统的性能。

流量削峰:这种一般在秒杀的业务中经常出现,突然请求爆增时候,服务器是不足以处理这么多请求,可能会系统崩溃,但是我们可以用MQ来进行削峰,请求进入消息队列排队,消费者来进行拉取请求消费,缓解了系统的压力。

拓展:RabbitMQ的灵魂3问

1.如何保证消息的可靠性呢?(如何保证发的消息不丢失)

我们可以从三个方面来回答:
1.保证生产者不丢失数据:我们可以开启confirm模式,将信道设置为confirm模式,每次发的消息都会给他分配一个唯一标识id,然后发送到RabbitMQ中的队列里,消息持久化到磁盘里,防止在队列中丢失,信道会给生产者发送一个确认,如果回传的是ack,说明消息一切正常,如果是nack,说明消息已经丢失了,生产者可以重新发送,来确保消息不丢失,这种模式是异步的,生产者应用程序在等待确认的同时,可以继续发送消息。
2.保证RabbitMQ本身不能搞丢数据:这个时候我们需要开启rabbitmq持久化,就是消息到了RabbitMQ我们要将消息写入到磁盘,以防万一RabbitMQ挂掉导致数据丢失,持久化后,重启的时候会自动加载之前持久化的数据,从而保证数据不丢失。
3.保证消费者不丢失数据:这个时候我们可以用RabbitMQ提供的ack机制,就是关闭rabbitmq自动ack,在每次自己代码里确保处理完的时候,手动调用ack,这样的话,如果还没处理完,就不会发送ack,RabbitMQ就会认为还没处理完,这个时候RabbitMQ会把这个消息分配给其他的consumer去处理,消息是不会丢的。(可能会造成消息重复消费)

2.如何保证消息不会被重复消费呢?

生产者发送消息,RabbitMQ会给每个生产者发送的消息生成一个inner-msg-id,作为去重和幂等的依据,防止重复的消息进入队列;消费者消费消息,要求消息中必须要有一个bizId(类似数据库中的id做唯一标识)作为去重和幂等的依据,防止同一条消息被重复消费。

3.RabbitMQ的缺点
1.系统可用性降低,MQ一旦挂了,影响很大,虽然MQ也有集群,可以实现高可用。据说有一线互联网公司MQ真的宕机过几小时,影响很大
2.使用MQ,我们需要考虑的更多了,导致系统复杂性增加,例如:消息的幂等性、消息如何进行可靠性投递、消息突然丢失了等
3.一致性问题。例如业务流程设计服务ABCD,需要保证原子性的,但是ABC都成功了,D失败了,这种时候就很蛋疼了
下面是我的个人公众号,免费分享面试资料和面试技术总结
教你如何应对面试中的RabbitMQ