0


RabbitMQ高可用--Quorum Queue(仲裁队列)的原理

原文网址:RabbitMQ高可用--Quorum Queue(仲裁队列)的原理_IT利刃出鞘的博客-CSDN博客

简介

说明

    本文介绍RabbitMQ的Quorum Queue(仲裁队列)的用法和原理。

    RabbitMQ从3.8.0版本开始加入仲裁队列功能,它是镜像队列的替代方案。它有队列复制的能力,保障数据的高可用和安全性。使用仲裁队列可以在 RabbitMQ 节点间进行队列数据的复制,在一个节点宕机时队列仍然可以提供服务。

官网网址

https://www.rabbitmq.com/quorum-queues.html

相关网址

RabbitMQ高可用--Quorum Queue(仲裁队列)的用法_IT利刃出鞘的博客-CSDN博客

备注

    RabbitMQ 已经有一个高可用队列的实现:镜像队列(Mirror Queues)。在 RabbitMQ 3.8.0 版本之前,镜像队列是实现数据高可用的唯一手段,但它有设计缺陷。仲裁队列旨在解决镜像队列的性能和同步问题。

仲裁队列的特性

  1. 仲裁队列用 Raft 算法实现了持久的、复制的 FIFO 队列,更加专注于数据安全。 1. 不会出现mirror queue出现的那样,两个节点件同一queue的数量落差很大的情况。2. Quorum队列中的消息要有集群中多半节点同意后,才会写到队列。这种队列类似于RocketMQ当中的Ledger集群,这种方式可以保证消息在集群内部不会丢失。
  2. Quorum queue到特定负载后,就不会继续接受新消息了。保持自身的平衡。

仲裁队列的使用场景

使用场景

  1. 队列长期存在
  2. 对容错、数据安全方面的要求比较高,能容忍响应慢些
  3. 不用持久化

不适合使用的场景

  1. 一些临时使用的队列:比如transient临时队列,exclusive独占队列,或者经常会修改和删除的队列
  2. 对消息低延迟要求高:一致性算法会影响消息的延迟
  3. 对数据安全性要求不高:Quorum队列需要消费者手动通知或者生产者手动确认
  4. 队列消息积压严重:如果队列中的消息很大,或者积压的消息很多,就不要使用Quorum队列。Quorum队列当前会将所有消息始终保存在内存中,直到达到内存使用极限。

仲裁队列和镜像队列的对比

Feature

Classic Mirrored

Quorum

Non-durable queues

yes

no

Exclusivity

yes

no

Per message persistence

per message

always

Membership changes

automatic

manual

Message TTL (Time-To-Live)

yes

yes (since 3.10)

yes

yes

Queue length limits

yes

yes (except x-overflow: reject-publish-dlx)

Lazy behaviour

yes

Message priority

yes

no

Consumer priority

yes

yes

Dead letter exchanges

yes

yes

yes

Poison message handling

no

yes

yes

no

Poison Message(有毒的消息)

    这个是指消息一直不能被消费,就会导致消息不断的重新入队,这样这些消息就成为了毒消息。对于毒消息的处理,在经典队列中,可以通过设置入队次数上限的参数,将消息最终转入到死信队列处理,而在Quorum队列中,就有了更新的处理方式。

仲裁队列的优势

  1. 客户端不需要改变它们生产和订阅的方法,无需考虑队列类型。 1. 唯一的区别就是在客户端定义队列的时候需要定义成仲裁队列(代码中添加相关属性)
  2. 被解决当节点重新上线时,不会丢数据(解决了镜像队列同步的问题) 1. 主副本会直接从从副本中断的地方开始复制消息。复制的过程是非阻塞的,所以整个队列不会因为新的副本加入而收到影响。唯一的影响是网络使用率。2. 没有了同步问题,不仅让仲裁队列比镜像队列更可靠,同时,因为写入必须被超过半数的副本接受,所以不会因为脑裂而丢数据。
  3. Raft 协议比镜像队列的算法更有效率,可以提供更好的消息吞吐量。

总结起来,仲裁队列可以提供更高的性能、更好的数据安全性、更容易进行节点的滚动升级。

仲裁队列的劣势

特性更少

这些特性在仲裁队列的第一个版本中不会提供

  1. 非持久化消息
  2. 排它队列
  3. 队列/消息 TTL(超时时间)
  4. 一些规则(Policy)不可用,只有死信队列、队列长度限制可用
  5. 优先级
  6. 惰性队列
  7. 非全局的消息预取(Qos)

磁盘使用——写入放大

仲裁队列的磁盘和内存配置与普通队列不同。

普通队列

    普通队列使用“共享”存储模型,对于一条要投递到多个队列的消息,只会存储一次,其他队列只会保存这条消息的引用。也就是说,在发布-订阅模型下,一条将要投递到多个队列的消息,它的存储大小不会随着投递到的队列变多而线性增长。

    举个例子,我们用一个 fanout 类型的 exchange,绑定 10 个队列。这 10 个队列每个都设置 5个副本镜像队列。发布一条消息后,只有 5 条消息存储到集群中,每个节点存储 1 条。所以在这个情况下的写入放大是 5 倍。

仲裁队列

    仲裁队列在内存中使用“共享”的存储模型,在磁盘中,每条消息都会分别被存储。所以发布-订阅模型会造成更严重的写入放大,可能导致更大的磁盘使用,甚至不得不放弃使用仲裁队列。

    还是上面那个例子,当每个队列都变成仲裁队列,并且复制因子为 5 时,最终集群中的磁盘上存储了 50 条消息,每条消息的写入放大是 50 倍。

    因此,把 fanout 交换器和仲裁队列一起使用不太合适。

消息一直在内存中

    仲裁队列的所有消息一直会保存在内存中,这会增加内存的使用量,最终可能导致集群不可用。如果不进行一些检查和监控,队列消息不断堆积,可能会导致生产停止(内存高水位),直到消息被消费或者从内存中删除。所以当使用仲裁队列时,设置队列的长度限制非常重要。此外还有必要用惰性队列作为仲裁队列的死信队列,通过死信交换器将这些消息转发到死信队列中。

    因此,队列的规划和监控比普通场景更重要。下游(消费者和下游服务)的中断或者变慢可能导致多个队列消息堆积,需要有对应的规划和措施。你需要多少个仲裁队列、它们的写入速率时多少,当集群达到内存高水位时其他队列会不会收到影响?

失去多数节点时队列不可用

如果仲裁队列超过半数的副本永久丢失,那么队列数据就永久丢失了。即便有小部分的副本仍然可用,队列仍然没有办法恢复,只能被强制删除。虽然这种场景出现的可能性较小,但是仍有这样的危险存在。所以,推荐使用可靠的磁盘,并且把复制因子设置为 5 ~ 3。

延迟

    尽管仲裁队列的吞吐量更高,但是延迟也可能更高,这是由于使用了 Raft 协议。在仲裁队列中,所有消息都是持久化的,所有消息都会保存到每个副本的磁盘中。安全性是仲裁队列的主要目标。

本文转载自: https://blog.csdn.net/feiying0canglang/article/details/126738084
版权归原作者 IT利刃出鞘 所有, 如有侵权,请联系我们删除。

“RabbitMQ高可用--Quorum Queue(仲裁队列)的原理”的评论:

还没有评论