3.2.0 版本中的联合队列
我们在 RabbitMQ 3.2.0 中添加了对联合队列的支持。这篇博文解释了它们的作用以及如何使用它们。
(顺便说一句,如果这看起来像是一大段文字,请见谅,我的绘画技巧不怎么样。RabbitMQ 团队中更有艺术细胞的成员正在制作一些精美的图表……)
它们有什么用?
队列联邦背后的核心思想是处理不同 Broker 上队列之间的消息负载均衡。如果你有一组相互联邦的队列,那么生产者可以向其中发布消息,消费者也可以从中消费消息,而无需(过多地)考虑其地理位置。
因此,与主要针对发布-订阅场景的联邦交换机(各地的消费者都能看到在任何地方发布的消息)不同,联邦队列适用于工作队列场景(某个地方的消费者能够看到在任何地方发布的消息)。发布者可以发布到任何地方,联邦机制会自动将消息移动到可以被消费的地方,但同一时间消息应仅存在于一个位置。
顺便提一下,这与人们通常谈论的负载均衡方式不同。通常我们考虑的是“事前”负载均衡——想象一个发布者随机选择多个队列中的一个进行发布,每个队列都有一些本地消费者。这种方法的麻烦在于,如果某个队列的消费者处理速度滞后或完全停止工作,则没有机制来平滑处理。队列联邦实现的是“事后”负载均衡,它将消息移动到能够处理它们的地方。
自 3.1.x 版本以来,联邦链路的性能有所提升(在 no-ack 模式下速度提高了约一倍,在 on-confirm 模式下提高了 50%)。但我们仍然希望在能避免的情况下尽量不移动消息,因此队列联邦仅在队列 B 有消费者但没有消息,且队列 A 的消息积压超过了其消费者(即时)处理能力时,才会将消息从队列 A 移动到队列 B。队列联邦的理想使用者应该在每个独立的队列上平衡发布和消费,从而使联邦机制无需干预。😃至少在某个消费者处理滞后之前是这样……
它们不适用于什么?
既然交换机和队列都可以联邦,人们很容易想到:“好,我可以把所有东西都联邦起来,这样我就拥有了一个大型虚拟 Broker,就像一个具有分区容错能力的集群”。当然,正如我们的老朋友 CAP 定理所暗示的那样,事情并没有那么简单;如果你获得了 (P) 分区容错性,就必须牺牲其他东西,对于联邦而言,那就是 (C) 一致性。联邦队列在任何给定时刻只会将某条消息保存在一个位置;没有镜像机制。可以将其想象成 RAID-0,而不是 HA 的 RAID-1。
当然,如果你想要 RAID-10 的效果,也可以通过联邦将多个集群连接在一起……
那么如何联邦一个队列呢?
很简单!定义一个或多个上游(upstream),就像联邦交换机那样,然后定义一个匹配你队列的策略(policy),并定义 federation-upstream-set 或 federation-upstream,同样与交换机操作一致。更多详细信息请参阅文档,实际上它与联邦交换机的工作方式完全相同。