跳至主内容
版本:4.2

Broker 语义

此处我们描述 Broker 的语义。应与 AMQP 规范一起阅读。

tx 的语义

AMQP 0-9-1 中定义的 AMQP tx 类的语义,以及其在不同版本的 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
事务性交换器/队列/绑定创建/删除
事务性消息的消费/获取
单个队列的原子性
跨多个队列的原子性
错误检测(例如,无效的交换器)未定义即时即时即时
发送 'no_route' basic.return未定义即时提交时提交时
效果可见性 / 责任转移 / 持久性未定义提交时提交时提交时

总的来说,AMQP tx 类的行为,尤其是在 RabbitMQ 上的实现,更像是提供一个“批量处理”功能,而不是数据库世界中已知的 ACID 功能。

AMQP 事务仅适用于发布和确认。我们额外地使拒绝操作事务化。其他操作,如资源创建/删除,不是事务性的。因此,当任何涉及的交换器、队列或绑定被修改时,事务的行为是未定义的

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

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

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

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

AMQP 没有规定事务效果在 tx.commit 后何时可见,例如,已发布的が消息何时出现在队列中可供其他客户端消费,持久化消息何时写入磁盘等。在 RabbitMQ 中,tx.commit-ok 表明所有事务效果都已可见,并且 Broker 已接受事务中所有已发布消息的责任。

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

消息排序保证

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

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

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

独占队列和持久性

独占队列是指只要声明它的连接关闭,该队列就会被删除。尽管 AMQP 0-9-1 允许您声明一个持久化的独占队列,但其持久性毫无意义,因为一旦 Broker 停止,该队列就会消失。因此,RabbitMQ 将忽略声明独占队列时的持久化标志,并创建一个独占的临时队列。

获取帮助和提供反馈

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

帮助我们改进文档 <3

如果您想为本网站贡献改进,其源代码可在 GitHub 上找到。 签署贡献者 CLA,然后只需 fork 存储库并提交一个拉取请求。谢谢!

© . This site is unofficial and not affiliated with VMware.