关于RabbitMQ / AMQP中的消息顺序保证

时间:2018-12-03 15:24:15

标签: rabbitmq amqp

消息队列服务(包括RabbitMQ)的主要特征之一是保留消息发布顺序。在RabbitMQ documentation中已确认:

  

[QUOTE 1] (AMQP 0-9-1核心规范的4.7节)   保证订购的条件:消息发布于   一个通道,通过一个交换机,一个队列和一个   传出频道的接收顺序与原先相同   已发送。自2.7.0版以来,RabbitMQ提供了更强大的保证。

下面我们假设没有消费者在活动,以简化事情。我们正在通过一个渠道发布。

到目前为止,很好。

RabbitMQ还提供通知发布者某些出版物已被完全正确处理的可能性。 [*] here对此进行了说明。基本上,代理将发送basic.ackbasic.nack消息。该文档还说:

  

[QUOTE 2] basic.ack用于将路由到持久队列的持久消息   将消息持久保存到磁盘后发送。

     

在大多数情况下,RabbitMQ会在   发布顺序相同(这适用于发布于   单个渠道)。但是,会发出发布者确认   可以异步确认一条消息或一组   消息。发出确认的确切时间取决于   邮件的传递方式(持续还是暂时)以及   邮件路由到的队列的属性(请参见上文)。   也就是说,可以考虑将不同的消息准备就绪   在不同的时间确认。这表示确认   与它们各自的消息相比,它们可以以不同的顺序到达。   在以下情况下,应用程序不应依赖于确认的顺序   可能。

乍一看,这是有道理的:持久存储一条消息要比将其存储在内存中要花费更多的时间,因此,很可能在确认较早的持久消息之前到达对较新的瞬时消息的确认。

但是,如果我们在上面重新阅读有关消息顺序 [QUOTE 1] 的第一条引语,则会引起混淆。我会解释。假设我们正在向同一交换机发送两个消息:首先是持久消息,然后是瞬时消息。由于RabbitMQ声称保留消息顺序,因此如何在知道第一条/永久消息确实完全写入磁盘之前发送第二条/临时消息的确认?

换句话说,上面关于不合逻辑的确认顺序的评论 [QUOTE 2] 仅在两条消息分别路由到完全不同的目标队列的情况下才适用(如果发生这种情况,他们有不同的路由密钥,例如)?在那种情况下,我们不必保证 [QUOTE 1] 中所做的任何事情。

[*] 在大多数情况下,这表示“已排队”。但是,如果没有适用的路由规则,则无法将其排入目标队列。但是,这对于发布确认仍然是一个积极的结果。

更新

我在类似的问题上读过这个answer。这基本上表示没有任何保证。即使是最幼稚的实现,我们将消息2的发布延迟到收到消息1的确认之后,也可能不会导致所需的消息顺序。基本上,不满足 [QUOTE 1]

这正确吗?

1 个答案:

答案 0 :(得分:1)

来自this response on rabbitmq-users

RabbitMQ知道消息在队列中的位置,无论它是否是瞬时的。

我的猜测(我没有写文档的那部分)是ack排序部分主要试图传达的信息,即如果将两条消息路由到两个不同的队列,这些队列将同时处理/复制/持久化它们。关于多个队列中的顺序的推理非常困难。一条消息也可以进入多个队列。

尽管如此,RabbitMQ队列知道消息在哪些队列中的位置。一旦处理发布的通道接收到所有路由/传递确认,就会将其添加到要发送的确认列表中。请注意 列表的排序方式可能与原始版本的排序方式相同,也可能不一样,并且出于许多原因,担心此操作不切实际,最重要的是:用户通常主要关心队列中的排序。


注意: RabbitMQ团队监视the rabbitmq-users mailing list,并且有时仅在StackOverflow上回答问题。