当前位置:   article > 正文

RabbitMQ如何保证消息的可靠性?_rabbitmq怎么保证消息可靠性

rabbitmq怎么保证消息可靠性

        在了解RabbitMQ如何保证消息的可靠性之前,我们可以先看一下RabbitMQ的执行的过程。

         在一次消息的传递之间,要经历上面的几个步骤,如果我们要保证消息的可靠性,那么必须在这些过程中入手,分为三个部分:(1)生产者 (2)MQ本身 (3)消费者

(1) 生产者

        生产者将我们的数据发送到RabbitMQ的时候,在传输数据的过程中,可能会导致数据的丢失,那么我们怎么样才能保证传输的时候数据不丢失呢?RabbitMQ提供了以下两种处理方式。

  • 事务功能

     我们可以使用RabbitMQ提供的事务功能,在我们发送数据之前,通过语句channel.txSelect开启事务功能,然后就可以发送消息了。

  • 如果消息成功投递到RabbitMQ,那么事务提交成功,可通过语句channel.txCommit进行提交。
  • 如果消息没有成功被RabbitMQ接收到,生产者就会收到对应的异常报错,那么就可以回滚我们的事务,可通过语句channel.txRollback进行回滚。

        使用这种方式有个缺点就是:我们的吞吐量降低,因为开启这种方式十分地消耗性能,因此是不推荐的。因此可以使用其他的方式解决上面提到的问题。

  • confirm模式

        使用这种方法的时候,我们通过在生产者这边开启confirm模式,在我们每次发送消息的时候,就会对应地分配一个唯一的id

  • 如果我们的消息成功地写入到了RabbitMQ中,那么RabbitMQ就会对应地给我们回传一个ack消息,告诉我们这个消息成功地投递过去了。
  • 如果RabbitMQ并没有处理这个消息的话,那么就会回调一个nack接口,告诉我们这个消息接收失败了,我们可以试着重发。

我们可以通过上面的这个机制,在我们的内存里维护每个消息id的状态,如果说,超过一定的时间了,我们还没有接收到消息的回调,不清楚这条信息是否能够成功投递到我们的RabbitMQ中,那么我们可以自己进行重发。

  • 区别

        通过上面的分析,其实我们可以看出,事务机制与confirm机制最大的不同在于:事务机制是同步的,而confirm机制是异步的

        当我们使用事务机制的时候,我们提交了一个事务,此时就会堵塞在那边了,等待事务执行的结果,确认它是成功投递,还是发生异常没有投递到RabbitMQ中。

        而使用confirm机制的时候,由于实现的机制是异步的,我们在发送了一条消息了以后,就可以发送下一条信息了,投递过去的消息会在RabbitMQ接收到,并且通过异步回调我们一个接口通知我们这条消息接收到了,如果返回的时ack,那么就是成功投递,反之为nack就是没有成功,我们可以进行消息的重发。

总结:一般在生产者这边,为了避免数据的丢失,我们可以使用confirm机制进行消息的投送。

(2) MQ

        RabbitMQ会不会丢失我们的数据呢?显然是会的,假设RabbitMQ将消息发送给消费者的时候,刚好RabbitMQ挂掉了,这就很尴尬了,消息还没投递到消费者那边过去,这就导致了这个数据的丢失,所以RabbitMQ提供了持久化的机制,用于处理上面说到的问题。

        在开启了RabbitMQ的持久化机制以后,消息写入之后就会被持久化到磁盘当中,此时哪怕RabbitMQ自己挂掉了,我们在重启RabbitMQ的时候,就会进行恢复,自动读取之前存储的数据,所以说一般数据是不会丢的,设置持久化有以下两个步骤:

  • 第一,我们在创建queue的时候,需要将queue设置为持久化,这样子就可以保证RabbitMQ能持久化queue的元数据(exchange、queue、binding、user、policy等数据),但是不会持久化queue里面的数据。
  • 第二,发送消息的时候将消息的deliveryMode模式(交付模式)设置为2,此时就会将消息设置为持久化,RabbitMQ就会将消息持久到磁盘上去。

        这里必须注意的点就是,我们需要同时设置这两个持久化才行。此时哪怕RabbitMQ挂掉了,再次重启,也能从我们的磁盘中恢复queue,恢复queue中的数据。

        这里的持久化机制可以同上面讲到的confirm机制结合起来,只有当消息被持久化到磁盘了之后才能通知生产者ack了。所以说,哪怕是在持久化数据到磁盘之前,我们的RabbitMQ挂了,数据丢失了,生产者收不到ack,那么我们自己就可以进行重发了。

        当然,这里说的持久化机制其实还是有一点缺陷的。即使我们给RabbitMQ开启了持久化机制,也有一种可能,就是消息写到了RabbitMQ的时候,还没来得及持久化到磁盘的时候,很不巧,RabbitMQ就刚好挂掉了,那么就会导致数据丢失的问题。不过只是丢失的只是这一点点的数据,问题不大,毕竟出现这种事情的概率也比较低。

总结:我们可以开启RabbitMQ提供的持久化机制保证MQ这边不会丢失消息。

(3) 消费端

        在消费端,也就是consumer这边,当我们在消费这条消息的时候,才刚开始消费,结果此时的进程挂掉了,比如说刚好就重启了,就挺突然的,尴尬的是RabbitMQ都认为我们消费完了,这个时候数据就丢失了。当然我们也不用怕,RabbitMQ给我们提供了ack机制,用于处理这些情况。

        简单来说,我们可以关闭RabbitMQ的自动ack机制,采用手动ack机制来进行代替。在我们的代理里面,确保每次处理完一条消息了以后,自己在程序里面进行ack。这样子的话,如果我们还没有处理完一条消息,那么就不会返回ack,那么RabbitMQ就不会认为我们已经处理完消息了,这个时候RabbitMQ是会将这个消费分配给别的consumer区处理的,这样子就能保证我们的消息是不会丢失的。

总结:在消费者这端,我们可以用手动ack机制代替自动ack机制。

(4) 总结

        下面以一张图作为总结,对应给出了RabbitMQ如何保证消息可靠性的全部方案,如下:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/443108
推荐阅读
相关标签
  

闽ICP备14008679号