1、为什么使用RabbitMQ?
RabbitMQ是一款开源的,Erlang编写的,基于AMQP协议的,消息中间件;
优点
- 流量削峰,高并发缓存 消息缓冲
- 消息分发
- 应用解耦(系统拆分,分布式解耦)
- 异步处理(预约挂号业务处理成功后,异步发送短信、推送消息、日志记录等)
缺点
- 系统可用性降低(MQ中间件突然挂掉)
- 系统稳定性降低(消息丢失)
- 分布式一致性问题 ()
2、消息怎么路由?
消息路由有三部分:交换机、路由、绑定。
生产者把消息发布到交换机上;
绑定决定了消息如何从路由到特定的队列;
消息最终到达队列,并被消费者接收。
direct 一对一 | 如果消息中路由键【routing key】和Binding中的【binding key】一致,完全匹配,交换机就将消息发到对应的队列中。单播模式。分发策略:轮询分发(平均分发);公平分发(按消费能力分发,消费完毕一个再分发一个,不会堵塞); |
fanout 一对多 | 每个发到fonout类型交换机的消息,都会分到所有绑定的队列上去。每台子网的主机都获得一份复制的消息。 广播模式。转发消息的最快的。 |
topic 一对多 | 可以使来自不同源头的消息能够到达同一个队列。 使用topic交换器时,可以使用通配符,比如:“*” 匹配特定位置的任意文本, “.” 把路由键分为了几部分,“#” 匹配所有规则等。特别注意:发往topic交换器的消息不能随意的设置选择键(routing_key),必须是由"."隔开的一系列的标识符组成。 |
3、如何保证RabbitMQ不被重复消费?
为什么会重复消费:
正常情况下,消费者在消费消息的时候,消费完毕会发生一个确认消息给消息队列,消息队列确认消息已被消费,就会从消息队列里删掉该消息。但是因为网络传输等等故障,确认消息没有发送到消息队列,导致消息队列无法知道这条消息是否被消费成功了,就会再次发送这个“未被消费”的消息。
解决 ==》
保证消息的唯一性,就算是多次传输,不要让消息的多次消费带来影响,保证消费幂等性;
比如,在写入消息队列的数据做唯一标识,消费消息时候,根据唯一标识判断是否被消费过。
1.当拿到这个消息做数据库的insert操作。那就容易了,给这个消息做一个唯一主键,那么就算出现重复消费的情况,就会导致主键冲突,避免数据库出现脏数据。 |
2.当拿到这个消息做redis的set的操作,那就容易了,不用解决,因为你无论set几次结果都是一样的,set操作本来就算幂等操作。 |
3.如果上面两种情况还不行,准备一个第三方存储,来做消费记录。以redis为例,给消息分配一个全局id,只要消费过该消息,将<id,message>以K-V形式写入redis。那消费者开始消费前,先去redis中查询有没消费记录即可。 |
4、如何保证RabbitMQ消息的可靠传输?
消息不可靠的情况可能是消息丢失,劫持等原因;
丢失又分为:生产者丢失消息、消息列表丢失消息、消费者丢失消息;
生产者丢失
从生产者角度丢失数据,RabbitMQ 提供两种模式保证数据不丢失 ,transaction 和 confirm 。
transaction机制 | 发送消息前,开启事务(channel.txSelect()),然后发送消息,如果发送过程出现异常,事务就回滚(channel.txRollback()。如果发送成功,则提交事务(channel.txCommit())。缺点:吞吐量下降。 |
confirm模式 | 用的居多,一旦channel进入confirm模式,所有在该信道上发布的消息都将会被指派一个唯一的ID(从1开始),一旦消息被投递到所有匹配的队列上,rabbitMQ就会发送一个ACK给生产者(包括唯一ID),就这使得生产者得知消息已经正确到达目的队列。如果rabbitMQ没能处理该消息,则会发送一个Nack消息给你,你可以重试操作。 |
消息队列丢失:
处理消息队列丢失数据的情况,一般是开启持久化磁盘的配置。持久化配置和confirm机制配合使用,你可以在消息持久化磁盘后,再给生产者发送一个ACK信号。如果消息持久化之前,rabbitMQ崩溃了,那么生产者收不到ACK信号,就会自动重发。
1.将queue的持久化标识durable 设置为true ,则代表是一个持久化队列。
2.发送消息的时候 将deliveryMode =2。即使rabbitMQ挂了,重启后也能恢复数据。
消费者丢失:
消费者丢数据一般是因为采用了自动确认消息模式,改为手动确认消息。
消费者在收到消息后,处理消息之前,会自动回复rabbitMQ已收到消息。如果这时处理消息失败,就会丢失消息。
解决 ==》 处理消息成功后,手动回复确认消息。
5、如何保证RabbitMQ 消息的顺序性
单线程消费保证消息的顺序性,对消息进行编号,消费者处理消息是根据编号处理消息。
ref
activeMQ面试总结 https://blog.csdn.net/bird73/article/details/79835457
RabbitMQ几个常用面试题 https://www.cnblogs.com/woadmin/p/10537174.html
https://www.jianshu.com/p/eaafb1581e55
消息中间件面试题:消息队列的优缺点,区别 https://blog.csdn.net/wqc19920906/article/details/82193316