关于 RabbitMQ/AMQP 中的消息顺序保证
Regarding message order guarantees in 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 声称保留消息顺序,它如何在知道 first/persistent 消息确实完全写入磁盘之前发送 second/transient 消息的确认?
换句话说,关于不合逻辑的确认顺序的评论 [QUOTE 2] 是否仅适用于两条消息分别路由到完全不同的目标队列的情况(例如,如果他们有不同的路由密钥,可能会发生这种情况)?在这种情况下,我们不必像 [QUOTE 1].
中所做的那样保证任何事情
[*] 在大多数情况下,这意味着 'queued'。但是,如果没有适用的路由规则,则无法将其放入目标队列中。然而,这仍然是确认发表的积极成果。
更新
我在 answer 上读过关于类似问题的文章。这基本上是说没有任何保证。即使是最天真的实现,我们将消息 2 的发布延迟到收到消息 1 的确认之后,也可能不会产生所需的消息顺序。基本上,[QUOTE 1]不满足。
这是正确的吗?
来自 this response on rabbitmq-users
:
RabbitMQ 知道消息在队列中的位置,无论它是否是瞬时的。
我的猜测(我没有写那部分文档)ack 排序部分主要试图传达如果两条消息被路由到两个不同的队列,这些队列将同时 handle/replicate/persist 它们。关于在 多个 队列中排序的推理非常困难。一条消息也可以进入多个队列。
尽管如此,RabbitMQ 队列知道消息在哪些队列中的位置。一旦处理发布的通道收到所有 routing/delivery 确认,它就会被添加到要发送的确认列表中。请注意,
列表可能会或可能不会以与原始发布相同的方式排序,并且出于多种原因担心这是不切实际的,最重要的是:用户通常主要关心队列中的排序。
注意: RabbitMQ 团队监控 the rabbitmq-users
mailing list 并且有时只在 Whosebug 上回答问题。
消息队列服务(包括 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 声称保留消息顺序,它如何在知道 first/persistent 消息确实完全写入磁盘之前发送 second/transient 消息的确认?
换句话说,关于不合逻辑的确认顺序的评论 [QUOTE 2] 是否仅适用于两条消息分别路由到完全不同的目标队列的情况(例如,如果他们有不同的路由密钥,可能会发生这种情况)?在这种情况下,我们不必像 [QUOTE 1].
中所做的那样保证任何事情[*] 在大多数情况下,这意味着 'queued'。但是,如果没有适用的路由规则,则无法将其放入目标队列中。然而,这仍然是确认发表的积极成果。
更新
我在 answer 上读过关于类似问题的文章。这基本上是说没有任何保证。即使是最天真的实现,我们将消息 2 的发布延迟到收到消息 1 的确认之后,也可能不会产生所需的消息顺序。基本上,[QUOTE 1]不满足。
这是正确的吗?
来自 this response on rabbitmq-users
:
RabbitMQ 知道消息在队列中的位置,无论它是否是瞬时的。
我的猜测(我没有写那部分文档)ack 排序部分主要试图传达如果两条消息被路由到两个不同的队列,这些队列将同时 handle/replicate/persist 它们。关于在 多个 队列中排序的推理非常困难。一条消息也可以进入多个队列。
尽管如此,RabbitMQ 队列知道消息在哪些队列中的位置。一旦处理发布的通道收到所有 routing/delivery 确认,它就会被添加到要发送的确认列表中。请注意, 列表可能会或可能不会以与原始发布相同的方式排序,并且出于多种原因担心这是不切实际的,最重要的是:用户通常主要关心队列中的排序。
注意: RabbitMQ 团队监控 the rabbitmq-users
mailing list 并且有时只在 Whosebug 上回答问题。