RabbitMQ在每个阶段都有可能使消息发生丢失
我们在这里把他们简单归结为三个层面
层面一 :生产者发送消息没有到达交换机或者没有到达绑定的队列。
层面二:RabbitMQ宕机可能导致的消息的丢失。
层面三:消费者宕机导致消息丢失。
层面一的解决方法常见的是
1.生产者确认机制
RabbitMQ提供了publisher confirm机制来避免消息发送到Mq的过程中丢失,消息发送到Mq以后,会返回一个结果给发送者,表示消息的发送成功。
情况一:发送成功 生产者正常发送消息到队列之后会返回一个publish-confirm ack 这个意思是告诉生产者已经接收到消息了。
情况二:发送失败 这里的发送失败有两种,一种是生产者发送到交换机失败 此时返回 publish-confirm nack 。第二种是生产者发送到队列失败 返回 publish-return ack。

生产者的配置文件中加入以下配置:
publisher-confirm-type:有三种模式可以选择:
第一种是none:代表关闭confirm机制
第二种是 simple:表示同步阻塞并等待mq的回执消息,即发送完消息后不能干其他的事情,只能等待mq的回执,很显然这样效率很低。
第三种是correlated:MQ异步回调方式返回回执消息,即生产者发送完消息后可以干其他的事情,直到接收到mq的回执。很明显这种效率要优于第二种
解决问题的方案:
方案一:重发消息
方案二:记录日志
方案三:保存到数据库中定时发送,发送成功后删除表中的数据。
方案四:交给人工处理。
~生产者确认机制需要额外的网络和系统的资源开销,尽量不要使用。
~如果业务需要,那么无需开启publisher-return机制,因为一般路由失败都是自己业务的原因。
~对于nack消息可以有限次数的重试,依然失败则记录异常消息
层面二的解决方法常见的是
2.消息持久化
由于mq是基于内存存储消息的,那么在mq服务宕机等一些情况下可能导致消息的丢失。同时内存空间有限,当消费者出现故障或者处理过慢,会导致消息积压,mq会对消息做迁移(page out 写入磁盘)从而引发mq阻塞。我们将消息存储在磁盘上就避免了这个问题。
一 :持久化交换机。

这里要选择Durable,因为Transient是临时交换机,当mq宕机后会消失。
二 :持久化队列。

三 :持久化消息。
2-Persistent持久化 ,1-Non-persistent是不持久的。
如果不选择持久化队列,交换机,消息的话我们还有另一种方案
Lazy Queue(惰性队列)
惰性队列的特征如下
~接受到消息的时候直接存入磁盘而非内存(内存中只保留最近的消息)
~消费者需要消息的时候才会从磁盘中取出数据加载到内存
~支持数百万条的消息存储
在mq3.12版本后,所有的队列都是Lazy Queue模式,无法更改。
如果各位小伙伴的版本低于3.12那我这里提供了两种方式创建惰性队列

方案三解决方案: 消费者确认机制
RabbitMQ支持消费者确认机制,即:当消费者处理消息后可以向mq发送ack回执,mq收到消息后会在队列中删除该消息。
