消息队列服务(包括RabbitMQ)的主要特征之一是保留消息发布顺序。在RabbitMQ documentation中已确认:
[QUOTE 1] (AMQP 0-9-1核心规范的4.7节) 保证订购的条件:消息发布于 一个通道,通过一个交换机,一个队列和一个 传出频道的接收顺序与原先相同 已发送。自2.7.0版以来,RabbitMQ提供了更强大的保证。
下面我们假设没有消费者在活动,以简化事情。我们正在通过一个渠道发布。
到目前为止,很好。
RabbitMQ还提供通知发布者某些出版物已被完全正确处理的可能性。 [*] 。 here对此进行了说明。基本上,代理将发送basic.ack
或basic.nack
消息。该文档还说:
[QUOTE 2]
basic.ack
用于将路由到持久队列的持久消息 将消息持久保存到磁盘后发送。在大多数情况下,RabbitMQ会在 发布顺序相同(这适用于发布于 单个渠道)。但是,会发出发布者确认 可以异步确认一条消息或一组 消息。发出确认的确切时间取决于 邮件的传递方式(持续还是暂时)以及 邮件路由到的队列的属性(请参见上文)。 也就是说,可以考虑将不同的消息准备就绪 在不同的时间确认。这表示确认 与它们各自的消息相比,它们可以以不同的顺序到达。 在以下情况下,应用程序不应依赖于确认的顺序 可能。
乍一看,这是有道理的:持久存储一条消息要比将其存储在内存中要花费更多的时间,因此,很可能在确认较早的持久消息之前到达对较新的瞬时消息的确认。
但是,如果我们在上面重新阅读有关消息顺序 [QUOTE 1] 的第一条引语,则会引起混淆。我会解释。假设我们正在向同一交换机发送两个消息:首先是持久消息,然后是瞬时消息。由于RabbitMQ声称保留消息顺序,因此如何在知道第一条/永久消息确实完全写入磁盘之前发送第二条/临时消息的确认?
换句话说,上面关于不合逻辑的确认顺序的评论 [QUOTE 2] 仅在两条消息分别路由到完全不同的目标队列的情况下才适用(如果发生这种情况,他们有不同的路由密钥,例如)?在那种情况下,我们不必保证 [QUOTE 1] 中所做的任何事情。
[*] 在大多数情况下,这表示“已排队”。但是,如果没有适用的路由规则,则无法将其排入目标队列。但是,这对于发布确认仍然是一个积极的结果。
更新
我在类似的问题上读过这个answer。这基本上表示没有任何保证。即使是最幼稚的实现,我们将消息2的发布延迟到收到消息1的确认之后,也可能不会导致所需的消息顺序。基本上,不满足 [QUOTE 1] 。
这正确吗?
答案 0 :(得分:1)
来自this response on rabbitmq-users
:
RabbitMQ知道消息在队列中的位置,无论它是否是瞬时的。
我的猜测(我没有写文档的那部分)是ack排序部分主要试图传达的信息,即如果将两条消息路由到两个不同的队列,这些队列将同时处理/复制/持久化它们。关于多个队列中的顺序的推理非常困难。一条消息也可以进入多个队列。
尽管如此,RabbitMQ队列知道消息在哪些队列中的位置。一旦处理发布的通道接收到所有路由/传递确认,就会将其添加到要发送的确认列表中。请注意 列表的排序方式可能与原始版本的排序方式相同,也可能不一样,并且出于许多原因,担心此操作不切实际,最重要的是:用户通常主要关心队列中的排序。
注意: RabbitMQ团队监视the rabbitmq-users
mailing list,并且有时仅在StackOverflow上回答问题。