rabbitmq之确保消息不丢失

1、背景引入

在使用消息中间件(rabbitmq)时,令开发者最头痛的就是防止消息丢失问题,而消息丢失可能发生的位置主要为三种,分别为(1)消息发送到MQ中消费者消费未成功时突然宕机;(2)消息发送到MQ中MQ集群整体宕机;(3)消息发送到队列但未持久化到磁盘前MQ集群整体宕机

2、解决消息发送到MQ中消费者消费未成功时宕机问题

对于稍微了解RabbitMQ的开发者而言一定会知道RabbitMQ中ack消息确认机制,默认情况下只要消息从队列中发送到消费者,队列就会将消息删除,此时将会出现以上所说的第一种情况,这时就需要开发者在消费者代码中将ack参数设置为True,这样消息在完全消费以后将会返回给MQ一个确定的应答,通知MQ可以将这条消息删除了,但是还会出现一种情况,消费者服务端没宕机而是消息格式不正确等错误引起的消费失败,这时如果还返回ack则会出现消息丢失问题,所以应该在消费者代码中加入判断机制,未消费成功返回nack,手动ack机制之下的架构图如下所示:

3、解决消息发送到MQ中MQ集群整体宕机问题

默认情况下RabbitMQ的queue和message都没采用持久化的方式进行投递,所以MQ集群重启将会导致部分消息丢失,因此可以采用持久化的方式创建queue,同时采用持久化的方式发送消息到MQ集群,这样MQ集群将会吧消息持久化到磁盘中。此时如果消息还没来得及投递给消费者服务,然后MQ集群突然宕机了,数据是不会丢失的,因为MQ集群重启之后会自动从磁盘文件里加载出来没投递出去的消息,然后继续投递给消费者服务。同样,该方案沉淀下来的系统架构图,如下所示:

4、解决消息发送到队列但未持久化到磁盘前MQ集群整体宕机问题

一个最大的问题,就是生产者投递出去的消息,可能会丢失。丢失的原因有很多,比如消息在网络传输到一半的时候因为网络故障就丢了,或者是消息投递到MQ的内存时,MQ突发故障宕机导致消息就丢失了。针对这种生产者投递数据丢失的问题,RabbitMQ实际上是提供了一些机制的。比如,有一种重量级的机制,就是事务消息机制。采用类事务的机制把消息投递到MQ,可以保证消息不丢失,但是性能极差,经过测试性能会呈现几百倍的下降。所以说现在一般是不会用这种过于重量级的机制,而是会用轻量级的confirm机制。但是我们这篇文章还不能直接讲解生产者保证消息不丢失的confirm机制,因为这种confirm机制实际上是采用了类似消费者的ack机制来实现的。相关代码实现如下:

同样,该方案沉淀下来的系统架构图,如下所示:

 

posted @ 2019-04-23 10:53 从流飘荡 阅读(...) 评论(...) 编辑 收藏