Skip to main content
版本: 4.1

Broker 语义

本文档描述了 broker 语义。应与 AMQP 规范一起阅读。

tx 的语义

AMQP 的 tx 类的语义(如 AMQP 0-9-1 中定义)及其在不同版本的 RabbitMQ 服务器中的实现经常被误解。以下是行为的总结

特性

AMQP
0-9-1

RabbitMQ
< 2.6.0

RabbitMQ
2.6.0-2.7.1

RabbitMQ
>= 2.8.0

事务性 basic.publish
事务性 basic.ack
事务性 basic.reject
事务性 exchange/queue/binding 创建/删除
事务性消息消费/获取
单队列中的原子性
跨多队列的原子性
错误检测 (例如,无效的 exchange)未定义立即立即立即
发送 'no_route' basic.return未定义立即在提交时在提交时
效果可见性 / 责任转移 / 持久性未定义在提交时在提交时在提交时

总的来说,AMQP tx 类的行为,以及它在 RabbitMQ 上的实现,更接近于提供“批处理”功能,而不是数据库领域中已知的 ACID 能力。

AMQP 事务仅适用于发布和确认。我们还额外使拒绝操作具有事务性。其他操作(如资源创建/删除)不是事务性的。因此,当任何涉及的 exchange、queue 或 binding 被更改时,事务的行为是未定义的

在消费端,确认是事务性的,而不是消息的消费本身。因此,回滚时不会重新排队已消费的消息;客户端仍然可以在后续事务中确认/拒绝这些消息。

AMQP 仅当事务涉及单个队列时才保证原子性,即 tx 内的所有发布都路由到单个队列,并且所有确认都与从同一队列消费的消息相关。当涉及多个队列时,在 tx.commit 期间发生 broker 故障时,事务的效果可能仅在某些队列中可见。此外,即使在仅涉及单个队列的事务中,RabbitMQ 也不提供原子性保证,例如,tx.commit 期间的故障可能导致事务发布的一部分在 broker 重启后出现在队列中。

AMQP 没有指定何时应检测到事务性 basic.publishbasic.ack 命令中的错误(例如,缺少权限、引用未知的 exchange)。RabbitMQ 立即执行必要的检查(而不是在提交时),但请注意,basic.publishbasic.ack 都是异步命令,因此任何错误都将异步报告回客户端。

对于 basic.return,情况类似,但请注意早期和最近版本的 RabbitMQ 之间行为的细微变化。您始终会在 tx.commit-ok 之前收到任何 basic.return

AMQP 没有指定事务的效果应在 tx.commit 后何时变为可见,例如,已发布的消息何时将出现在队列中并可以从其他客户端消费,持久消息何时将写入磁盘等。在 RabbitMQ 中,tx.commit-ok 表示所有事务效果都可见,并且 broker 已接受对事务中发布的所有消息的责任。

对于确认,收到 tx.commit-ok 是服务器已收到确认的指示,而不是它们已被处理、持久化等。因此,后续的服务器端故障可能会“复活”已确认的消息,并且消费客户端会再次收到它们。

消息排序保证

AMQP 0-9-1 核心规范的 4.7 节解释了保证排序的条件:在一个通道中发布的消息,通过一个 exchange 和一个 queue 以及一个传出通道,将以它们发送的相同顺序接收。自 2.7.0 版本以来,RabbitMQ 提供了更强的保证。

可以使用具有 requeue 参数的 AMQP 方法(basic.recoverbasic.rejectbasic.nack)或由于通道关闭而持有未确认的消息,将消息返回到队列。对于早于 2.7.0 的 RabbitMQ 版本,任何这些情况都会导致消息在队列末尾重新排队。从 RabbitMQ 2.7.0 版本开始,即使存在重新排队或通道关闭,消息也始终按发布顺序保存在队列中。

在 2.7.0 及更高版本中,如果队列有多个订阅者,则单个消费者仍然可能观察到乱序的消息。这是由于其他订阅者可能重新排队消息的操作所致。从队列的角度来看,消息始终按发布顺序保存。

独占队列和持久性

独占队列是指在声明它的连接关闭时删除的队列。尽管 AMQP 0-9-1 允许您声明持久的独占队列,但持久性是毫无意义的,因为一旦 broker 停止,队列无论如何都会消失。因此,RabbitMQ 将忽略独占队列声明中的 durable 标志,并创建一个独占的瞬态队列。

获取帮助和提供反馈

如果您对本指南的内容或与 RabbitMQ 相关的任何其他主题有疑问,请随时使用 GitHub Discussions 或我们的社区 Discord 服务器提问。

帮助我们改进文档 <3

如果您想为改进站点做出贡献,其源代码在 GitHub 上可用。只需 fork 存储库并提交 pull request。谢谢!

© . All rights reserved.