作者 | 黄永灿
![a6497b3315db06046065b701bcaab036.png](https://i-blog.csdnimg.cn/blog_migrate/0392d694f7c2407a4b06a8ba70ae1980.jpeg)
后端开发攻城狮,关注服务端技术与性能优化。
RabbitMQ 的消息发送机制
在讨论 RabbitMQ 的消息可靠性之前,我们先来回顾一下消息在 RabbitMQ 中是怎么流转的。
消息生产端将消息发送给 Exchange
Exchange 根据 RoutingKey 把消息路由至具体 Queue
消息消费端监听 Queue 并消费消息
那么,这几个步骤有哪些地方可能会掉链子导致消息丢失呢?
- Producer 到 Exchange 这一步发生网络故障或是丢包导致 Exchange 没收到消息
- 消息在 Exchange 没有匹配到 Queue
- 消息在 Queue 中还没被消费时 RabbitMQ 挂了
- 消息在 Queue 传输给 Consumer 的时候出现网络故障,或是消息消费失败了
如何保证消息的可靠性
接下来,我们会把整个消息传输过程拆分成三个步骤来讨论分别如何保证每一步的可靠性。第一步:生产端到RabbitMQ
方案一:事务机制
为了保证这一步的可靠性,AMQP 协议在建立之初就提供了事务机制。 RabbitMQ 客户端中与事务机制相关的方法有三个: channel.txSelect、channel.txCommit 以及 channel.txRollback。 channel.txSelect 用于将当前的信道设置成事务模式,channel.txCommit 用于提交事务,而 channel.txRollback 用于事务回滚。 在通过channel.txSelect 方法开启事务之后,我们便可以发布消息给 RabbitMQ 了,如果事务提交成功,则消息一定到达了 RabbitMQ 中,如果在事务提交执行之前由于 RabbitMQ 异常崩溃或者其他原因抛出异常,这个时候我们便可以将其捕获,进而通过执行 channel.txRollback 方法来实现事务回滚。try {
// 开启事务
channel.txSelect();
// 发送消息
channel.basicPublish(exchange, routingKey, props, body);
// 事务提交
channel.txCommit();
} catch(Exception e) {
// 事务回滚
channel.txRollback();
e.printStackTrace();
}
方案二:Confirm机制
上面的事务机制虽然保证了消息投递端的可靠性,但因为每次投递都开启了事务,所以性能较低,一般不推荐使用,接下来要讲的 Confirm 机制就比较好的兼顾了性能以及可靠性。开启 Confirm 机制后,所有在该信道上面发布的消息都会被指派一个唯一的ID(从 1 开始),一旦消息被投递到所有匹配的队列之后&#PS:事务机制和 Confirm 机制是互斥的,两者不能共存,会导致 RabbitMQ 报错。