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

包含RabbitMQ的消息队列服务的一个主要特征是保留消息发布顺序.这已在
RabbitMQ documentation中得到确认:

[QUOTE 1] Section 4.7 of the AMQP 0-9-1 core specification explains the
conditions under which ordering is guaranteed: messages published in
one channel, passing through one exchange and one queue and one
outgoing channel will be received in the same order that they were
sent. RabbitMQ offers stronger guarantees since release 2.7.0.

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

到现在为止还挺好.

RabbitMQ还提供了通知发布者某个出版物已被完全和正确处理的可能性[*].这是解释here.基本上,代理将发送basic.ack或basic.nack消息.文档还说:

[QUOTE 2] basic.ack for a persistent message routed to a durable queue will be
sent after persisting the message to disk.

In most cases, RabbitMQ will acknowledge messages to publishers in the
same order they were published (this applies for messages published on
a single channel). However, publisher acknowledgements are emitted
asynchronously and can confirm a single message or a group of
messages. The exact moment when a confirm is emitted depends on the
delivery mode of a message (persistent vs. transient) and the
properties of the queue(s) the message was routed to (see above).
Which is to say that different messages can be considered ready for
acknowledgement at different times. This means that acknowledgements
can arrive in a different order compared to their respective messages.
Applications should not depend on the order of acknowledgements when
possible.

乍一看,这是有道理的:持久化消息比将其存储在内存中花费更多的时间,因此很可能在确认早期持久消息之前确认稍后的瞬态消息.

但是,如果我们重新阅读上面关于消息顺序的第一个引用[QUOTE 1],那就会让人感到困惑.我会解释一下.假设我们向同一个交换机发送两条消息:首先是持久消息,然后是瞬态消息.由于RabbitMQ声称保留了消息顺序,它如何在知道第一个/持久消息确实完全写入磁盘之前发送第二个/瞬态消息的确认?

换句话说,上面关于不合逻辑的确认顺序[QUOTE 2]的注释是否仅适用于两个消息都被路由到完全不同的目标队列的情况(例如,如果它们具有不同的路由密钥,则可能会发生这种情况)?在这种情况下,我们不必像[QUOTE 1]那样保证任何事情.

[*]在大多数情况下,这意味着“排队”.但是,如果没有适用的路由规则,则无法将其排入目标队列.然而,这仍然是有关出版物确认的积极结果.

更新

我在类似问题上阅读了这篇answer.这基本上说没有任何保证.即使是最天真的实现,我们将消息2的发布延迟到我们收到消息1的确认之后,也可能不会产生所需的消息顺序.基本上,不符合[QUOTE 1].

它是否正确?

最佳答案 从
this response on rabbitmq-users开始:

RabbitMQ知道队列中的消息位置,无论它是否是瞬态的.

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

尽管如此,RabbitMQ队列知道消息在哪些队列中的位置.一旦处理了发布的通道收到所有路由/传递确认,它就会被添加到要发送的确认列表中.请注意
列表可能会或可能不会以与原始发布相同的方式进行排序,并且由于许多原因而担心这是不切实际的,最重要的是:用户通常主要关心队列中的排序.

注意:RabbitMQ团队监控the rabbitmq-users mailing list,有时只回答StackOverflow上的问题.

点赞