前言
本文是对RabbitMQ的常见面试题问答的总结,同时也是一个RabbitMQ的入门学习,还没了解的同学快来认识一下。
1.RabbitMQ消息模型有哪些?
(1)HelloWorld 模型(点对点模型)
- 一个生产者
- 一个消息队列
- 一个消费者
(2)WorkQueues 模型(任务模型)
- 一个生产者
- 一个消息队列
- 多个消费者
(3)Publish/Subscribe 模型(广播模型)
- 一个生产者
- 一个 fanout 交换机
- 多个消息队列
- 多个消费者
- 交换机绑定多个队列
- 每个消息队列绑定一个消费者
(4)Routing 模型(路由模型)
- 一个生产者
- 一个 direct 交换机
- 多个消息队列
- 多个消费者
- 交换机绑定多个队列
- 每个消息队列绑定一个消费者
(5)Topics 模型(动态路由模型)
- 一个生产者
- 一个 topic 交换机
- 多个消息队列
- 多个消费者
- 交换机绑定多个队列
- 每个消息队列绑定一个消费者
参考资料:https://blog.csdn.net/F0217911/article/details/126621205
2.RabbitMQ的使用场景有哪些?
(1)异步处理:比如用户注册或登录时,生产者发送消息到MQ队列,消费者再读取处理消息,执行发送短信和邮件动作。
(2)系统解耦:比如用注册完成,再加一个发送微信通知。只需要新增发送微信消息模块,从MQ中读取任务,发送消息即可。无需改动注册模块的代码,这样注册模块与发送模块通过MQ解耦。
(3)流量削峰:秒杀和抢购等场景经常使用MQ进行流量削峰。活动开始时流量暴增,用户的请求写入MQ,超过MQ最大长度丢弃请求,业务系统接收 MQ中的消息进行处理,达到流量削峰、保证系统可用性的目的。
3.你们用RabbitMQ实现了什么功能?
(1)基于RabbitMQ+Redis+DiyThreadPool实现按顺序幂等消费消息执行任务。
4.如何保证消息幂等性?
消息幂等性是指对于同一条消息,无论重复发送多少次,接收端都只接收到一次消息,且消息的处理结果相同。
(1)生产者生成消息时,每条消息都有唯一ID字段,可以使用UUID或者Snowflake算法等方式生成。
(2)消费者在处理消息时,先根据ID去Redis查询是否存在该消息,若不存在则正产消费,消费完存入此ID到Redis,若存在则说明此消息已被消费过,直接丢弃。
5.如何保证消息顺序性?
很多时候,消息的消费是不用保证顺序的,比如借助mq实现订单超时的处理。但有些时候,业务中可能会存在多个消息需要顺序处理的情况,比如生成订单和扣减库存消息,那肯定是先执行生成订单的操作,再执行扣减库存的操作。
(1)一个消息队列对应一个消费者:这种方法最简单,保证消息是按照顺序进行的。
(2)一个消息队列对应多个消费者:要想保证消息是按照顺序进行的,就得开启单活模式,表示是否最多只允许一个消费者消费,如果有多个消费者同时绑定,则只会激活第一个,除非第一个消费者被取消或者死亡,才会自动转到下一个消费者。
参考资料:https://baijiahao.baidu.com/s?id=1773108861109586675
6.如何避免消息堆积?
消息队列的消息堆积可能是由于消费者无法及时处理消息、消费者处理消息的速度跟不上消息的产生速度、消息队列的容量不足等原因造成的。
(1)增加消息队列数量。
(2)增加消费者数量。
(3)通过自定义线程池异步消费。
7.如何避免消息丢失?
丢失情况主要有生产者丢失消息、消息队列丢失消息、消费者丢失消息三种情况。
(1)消息确认机制。
(2)消息持久化。
8.RabbitMQ中推模式和拉模式的区别
(1)推模式是中间件将消息提前推送给消费者,消费者需设置一个缓冲区缓存消息。好处是消费者总是有一堆在内存中待处理的消息,所以效率高,缺点是缓冲区可能会溢出。
(2)拉模式是消费者有需要时才去中间件拉取消息。
(3)推模式更关注实时性,拉模式更关注消费者的消费能力。