2、RabbitMQ基础知识

1、什么是RabbitMQ?
是消息中间件的一种,RabbitMQ是由erlang语言开发,基于AMQP(Advanced Message Queue 高级消息队列协议)协议实现的消息队列,它是一种应用程序之间的通信方法。通过高效可靠的消息传递机制进行与平台无关的数据交流。基于数据通信来进行分布式系统的集成,通过提供消息传递和消息队列模型,可以在分布式环境下扩展进程的通信。消息队列在分布式系统开发中应用非常广泛。
2、RabbitMQ的使用场景或者功能?
1)服务间异步通信:对于数据量大或者处理耗时长的操作,我们可以引入 MQ 实现异步通信,减少客户端的等待,提升响应速度(如:日志记录)。
2)系统解耦:对于改动影响大的系统之间,可以引入 MQ 实现解耦,减少系统之间的直接依赖(如:订单取消后解锁库存、退还支付金额、发送消息通知)。
3)流量削峰:对于会出现瞬间的流量峰值的系统,我们可以引入 MQ 实现流量削峰,达到保护应用和数据库的目的(如:商品抢购预定)。
4)消息通讯:消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯。比如实现点对点消息队列,或者聊天室等。
5)顺序消费
6)定时任务
3、重复消费是如何产生的?
正常情况下,消费者在消费消息的时候,消费完毕后,会发送一个确认消息给消息队列,消息队列就知道该消息被消费了,就会将该消息从消息队列中删除;但是因为网络传输等等故障,确认信息没有传送到消息队列,导致消息队列不知道该消息已经被消费掉了,会再次将消息分发给其他的消费者或者向同一个消费者发送了两条同样的消息记录。
4、重复消费如何解决?
1)保证消息的唯一性,就算是多次传输,不要让消息的多次消费带来影响,保证消费消息是幂等的;
2)在写入消息队列的数据做唯一标示,消费消息时,根据唯一标识在消费日志表中判断是否被消费过;
4、如何保证RabbitMQ消息的可靠传输?
消息丢失包括:生产者丢失消息、消息列表丢失消息、消费者丢失消息;
1)生产者丢失消息:
RabbitMQ提供transaction和confirm模式来确保生产者不丢消息
a.transaction模式:
发送消息前,开启事务(channel.txSelect()),然后发送消息,如果发送过程中出现什么异常,事务就会回滚(channel.txRollback()),如果发送成功则提交事务(channel.txCommit()),然而这种方式有个缺点就是会导致吞吐量下降。
b.confirm模式:
当channel进入confirm模式,所有在该信道上发布的消息都将会被指派一个唯一的ID(从1开始),一旦消息被投递到所有匹配的队列之后;rabbitMQ就会发送一个ACK给生产者(包含消息的唯一ID),这就使得生产者知道消息已经正确到达目的队列了;如果rabbitMQ没能处理该消息,则会返回一个Nack消息表示可以进行重试操作。

2)消息队列丢数据:
处理消息队列丢数据的情况,一般是开启持久化磁盘的配置。这个持久化配置可以和confirm机制配合使用,可以在消息持久化磁盘后,再给生产者发送一个Ack信号。这样,如果消息持久化磁盘之前,rabbitMQ挂掉,那么生产者收不到Ack信号,生产者会自动重发。那么如何进行持久化呢?具体如下:
a.将queue的持久化标识durable设置为true,则代表是一个持久的队列
b.发送消息的时候将deliveryMode=2
这样设置以后,即使rabbitMQ挂了,重启后也能恢复数据

3)消费者丢失消息:
消费者丢数据一般是因为采用了自动确认消息模式,改为手动确认消息即可。具体如下:
a.自动确认消息模式:消费者在收到消息之后,处理消息之前,会自动回复RabbitMQ已收到消息;
b.手动确认消息模式:消费者在收到消息之后,在当处理消息成功后,手动回复确认消息。
5、如何保证RabbitMQ消息的顺序性(消息有序指的是可以按照消息的发送顺序来消费)?
问题详情:假如生产者产生了 2 条消息:M1、M2,假定 M1 发送到 S1,M2 发送到 S2,如果要保证 M1 先于 M2 被消费,怎么做?
1)保证生产者-MQServer-消费者是一对一对一的关系,消费端单线程消费保证消息的顺序性,但是这样会导致吞吐量下降,并且一旦消费端出现问题,将导致消费队列发生堵塞。
2)对消息进行编号,消费者处理消息是根据编号处理消息;
3)可以考虑从业务层面来保证消息的顺序而不仅仅是依赖于消息系统,是一种更合理的方式;
6、如何确保消息正确地发送至 RabbitMQ?
采用发送方确认模式,即将信道设置成 confirm 模式(发送方确认模式),则所有在信道上发布的消息都会被指派一个唯一的 ID。一旦消息被投递到目的队列后,或者消息被写入磁盘后(可持久化的消息),信道会发送一个确认给生产者(包含消息唯一 ID)。如果 RabbitMQ 发生内部错误从而导致消息丢失,会发送一条 nack(notacknowledged,未确认)消息。发送方确认模式是异步的,生产者应用程序在等待确认的同时,可以继续发送消息。当确认消息到达生产者应用程序,生产者应用程序的回调方法就会被触发来处理确认消息。
7、RabbitMQ 如何确保消息接收方消费了消息?
采用接收方确认机制,消费者接收每一条消息后都必须进行确认(消息接收和消息确认是两个不同操作)。只有消费者确认了消息,RabbitMQ 才能安全地把消息从队列中删除。这里并没有用到超时机制,RabbitMQ 仅通过 Consumer 的连接中断来确认是否需要重新发送消息。也就是说,只要连接不中断,RabbitMQ 给了 Consumer 足够长的时间来处理消息,保证数据的最终一致性。但是当遇到两种异常RabbitMQ是会如何处理呢?
如果消费者接收到消息,在确认之前断开了连接或取消订阅,RabbitMQ 会认为消息没有被分发,然后重新分发给下一个订阅的消费者。(可能存在消息重复消费的隐患,需要去重)
如果消费者接收到消息却没有确认消息,连接也未断开,则 RabbitMQ 认为该消费者繁忙,将不会给该消费者分发更多的消息。
8、RabbitMQ 如何保障高可用?
采用集群模式。RabbitMQ 有三种模式:单机模式、普通集群模式、镜像集群模式。
1)普通集群模式:
在多台机器上启动多个 RabbitMQ 实例,每个机器启动一个;
创建的 queue,只会放在一个 RabbitMQ 实例上,但是每个实例都同步 queue 的元数据(元数据可以认为是queue 的一些配置信息,通过元数据,可以找到 queue 所在实例);
消费的时候,实际上如果连接到了另外一个实例,那么那个实例会从 queue 所在实例上拉取数据过来。这方案主要是提高吞吐量的,就是说让集群中多个节点来服务某个 queue 的读写操作;
2)镜像集群模式:真正的高可用模式。
跟普通集群模式不一样的是,在镜像集群模式下:
创建的 queue,无论元数据还是 queue 里的消息都会存在于多个实例上,就是说,每个 RabbitMQ 节点都有这个 queue 的一个完整镜像,包含 queue 的全部数据的;
每次你写消息到 queue 的时候,都会自动把消息同步到多个实例的 queue 上;
RabbitMQ 有很好的管理控制台,就是在后台新增一个策略,这个策略是镜像集群模式的策略,指定的时候是可以要求数据同步到所有节点的,也可以要求同步到指定数量的节点,再次创建 queue 的时候,应用这个策略,就会自动将数据同步到其他的节点上去了。这样的好处在于,任何一个机器宕机了,其它机器(节点)还包含了这个 queue 的完整数据,别的 consumer 都可以到其它节点上去消费数据。坏处在于,增大性能开销,消息需要同步到所有机器上,导致网络带宽压力和消耗加重,RabbitMQ 一个 queue 的数据都是放在一个节点里的,镜像集群下,也是每个节点都放这个 queue 的完整数据。



参看博文:
https://www.cnblogs.com/woadmin/p/10537174.html
https://blog.csdn.net/thinkwon/article/details/104588612/
原文地址:https://www.cnblogs.com/jiarui-zjb/p/14314889.html