RabbitMQ 教程

消息传输可靠性

当业务系统在接入 RabbitMQ 消息中间件时,首要考虑的问题是消息的可靠性传输,一般消息中间件的消息传输的可靠性分为三个层级:

  • 最多一次(At Most Once):消息可能会丢失,但绝不会重复传输

  • 最少一次(At Least Once ):消息绝不会丢失,但可能会重复传输

  • 恰好一次(Exactly Once):每条消息肯定会被传输一次且仅传输一次

注意:在 RabbitMQ 中,只支持其中的 “最多一次” 和 “最少一次”。

最少一次(At Most Once)

实现 “最少一次” 需要考虑以下几个方面的内容:

(1)消费者在消费消息的同时需要将 autoAck 设置为 false,然后通过手动确认的方式去进行消费确认操作,以避免在消费端导致消息丢失。

(2)消息生产者需要开启事务机制或发送方确认机制(Publisher Confirm),以确保消息可以可靠地传输到 RabbitMQ 中。

(3)消息生产者需要配合使用 mandatory 参数或者备份交换器来确保消息能够从交换器路由到队列中,进而能够保存下来而不会被丢弃。

(4)消息和队列都需要进行持久化处理,以确保 RabbitMQ 服务器在遇到异常情况时不会造成消息丢失。

最多一次(At Least Once )

即消息可能会丢失,但绝不会重复传输。“最多一次” 的方式就无须考虑事务机制、发送方确认机制、持久化处理、手动确认等等。生产者随意发送消息,消费者随意消费消息,不过这样很难确保消息不会丢失,这适合那些对消息丢失可以容忍的应用,例如:实时监测设备状态,即使丢失几个消息并不影响,因为很快会有新消息到来。

恰好一次(Exactly Once)

“恰好一次” 是 RabbitMQ 目前无法保障的。

考虑这样一种情况,消费者在消费完一条消息之后向 RabbitMQ 发送确认 Basic.Ack 命令,此时由于网络断开或者其他原因造成 RabbitMQ 并没有收到这个确认命令,那么 RabbitMQ 不会将此条消息标记删除。客户端在重新建立连接之后,消费者还是会消费到这条消息,这就造成了重复消费。

再考虑一种情况,生产者在使用发送方确认机制(Publisher Confirm)的时候,发送完一条消息等待 RabbitMQ 返回确认通知,此时网络断开,生产者捕获到异常情况,为了确保消息可靠性选择重新发送,这样 RabbitMQ 中就有两条同样的消息,在消费的时候,消费者就会重复消费。

那么 RabbitMQ 有没有去重的机制来保证 “恰好一次” 呢?答案是并没有,不仅是 RabbitMQ 没有,目前大多数主流的消息中间件都没有消息去重机制,也不保障 “恰好一次”。

去重处理一般是在业务客户端实现,比如引入 GUID(Globally Unique Identifier)的概念。针对 GUID ,如果从客户端的角度去 ,那么需要引入集中式缓存,必然会增加依赖复杂度,另外缓存的大小也难以界定。

说说我的看法
全部评论(
没有评论
关于
本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,请来信告知:hxstrive@outlook.com
公众号