RabbitMQ消息可靠性分析

  

介绍   

有很多人问过我这么一类问题:<强> RabbitMQ如何确保消息可靠? 很多时候,笔者的回答都是:说来话长的事情何来长话短说。的确,要确保消息可靠不只是单单几句就能够叙述明白的,包括卡夫卡也是如此。可靠并不是一个绝对的概念,曾经有人也留言说过类似全部磁盘损毁也会导致消息丢失,笔者戏答:还有机房被炸了也会导致消息丢失。可靠性是一个相对的概念,在条件合理的范围内系统所能确保的多少个9的可靠性。一切尽可能的趋于完美而无法企及于完美。
我们可以尽可能的确保RabbitMQ的消息可靠。在详细论述RabbitMQ的消息可靠性之前,我们先来回顾下消息在RabbitMQ中的经由之路。
 RabbitMQ消息可靠性分析“> <br/>如图所示,从AMQP协议层面上来说:</p>
  <p>消息先从生产者生产出发到达交换器交换;<br/>交换器交换根据路由规则将消息转发对应的队队列之列上;<br/>消息在队列队列上进行存储;<br/>消费者消费者订阅队列队列并进行消费。<br/>我们对于消息可靠性的分析也从这四个阶段来一一探讨。</p>
  <h4> </h4>第一阶段
  <p>消息从生产者发出到达交换器交换,在这个过程中可以发生各种情况,生产者客户端发送出去之后可以发生网络丢包,网络故障等造成消息丢失。一般情况下如果不采取措施,生产者无法感知消息是否已经正确无误的发送到交换器中。如果消息在传输到交换的过程中发生失败而可以让生产者感知的话,生产者可以进行进一步的处理动作,比如重新投递相关消息以确保消息的可靠性。</p>
  <p>为此AMQP协议在建立之初就考虑到这种情况而提供了事务机制.RabbitMQ客户端中与事务机制相关的方法有三个:channel.txSelect, channel.txCommit以及channel.txRollback.channel.txSelect用于将当前的信道设置成事务模式,channel.txCommit用于提交事务,而channel.txRollback用于事务回滚。在通过channel.txSelect方法开启事务之后,我们便可以发布消息给RabbitMQ了,如果事务提交成功,则消息一定到达了RabbitMQ中,如果在事务提交执行之前由于RabbitMQ异常崩溃或者其他原因抛出异常,这个时候我们便可以将其捕获,进而通过执行channel.txRollback方法来实现事务回滚。注意这里的RabbitMQ中的事务机制与大多数数据库中的事务概念并不相同,需要注意区分。</p>
  <p>事务确实能够解决消息发送方和RabbitMQ之间消息确认的问题,只有消息成功被RabbitMQ接收,事务才能提交成功,否则我们便可在捕获异常之后进行事务回滚,与此同时可以进行消息重发。但是使用事务机制的话会“吸干“RabbitMQ的性能,那么有没有更好的方法既能保证消息发送方确认消息已经正确送达,又能基本上不带来性能上的损失呢?从AMQP协议层面来看并没有更好的办法,但是RabbitMQ提供了一个改进方案,即发送方确认机制(发布者证实)。</p>
  <p>生产者将信道设置成确认(确认)模式,一旦信道进入确认模式,所有在该信道上面发布的消息都会被指派一个唯一的ID(从1开始),一旦消息被投递到所有匹配的队列之后,RabbitMQ就会发送一个确认(Basic.Ack)给生产者(包含消息的唯一ID),这就使得生产者知晓消息已经正确到达了目的地了.RabbitMQ回传给生产者的确认消息中的deliveryTag包含了确认消息的序号,此外RabbitMQ也可以设置通道。basicAck方法中的多个参数,表示到这个序号之前的所有消息都已经得到了处理。<br/> <img src=RabbitMQ消息可靠性分析