详解RabbitMQ三种队列类型

RabbitMQ 是一个强大的消息队列系统,它提供了多种队列类型以满足不同的使用需求。本文将探讨三种主要队列类型:经典队列、仲裁队列和流式队列,并讨论它们的区别和选型建议。

经典队列(Classic Queues)

简介:

经典队列是 RabbitMQ 中最早期也是最常用的一种队列类型。它们具有良好的性能和稳定性,适合大多数常规的消息传递场景。

特点:

  • 存储机制:消息存储在磁盘或内存中,支持持久化。

  • 消息传递:一旦消息被消费者确认,消息会从队列中删除。

  • 性能:性能相对较高,但在高并发和大消息量场景下,可能会遇到瓶颈。

  • 高可用性:支持镜像队列,实现高可用性。镜像队列中的消息会复制到多个节点,以防单节点故障。

适用场景:

适合大多数常规消息传递场景,如任务调度、事件通知等。

当需要消息的持久化存储和高可靠性时,经典队列是一个很好的选择。

仲裁队列(Quorum Queues)

简介:

仲裁队列是一种基于 Raft 协议实现的新型队列,专为提高数据一致性和可靠性而设计。

特点:

  • 存储机制:消息存储在多个节点上,采用 Raft 协议确保数据一致性。

  • 高可用性:天然支持高可用性,通过多节点复制实现数据冗余。

  • 数据一致性:仲裁队列确保每条消息在多个副本之间的一致性,避免单点故障导致的数据丢失。

  • 性能:由于需要确保数据一致性,性能可能比经典队列略低,适合对数据一致性要求较高的场景。

适用场景:

  • 适用于对数据一致性和高可用性要求较高的场景,如金融交易、订单处理等关键业务系统。

  • 在需要确保消息不丢失且需要高可用性的情况下,仲裁队列是一个理想选择。

注意事项

  1. 仲裁队列只能声明为持久的

仲裁队列只能被声明为持久的,否则会引发以下错误消息: :server_initiated_close,406,“PRECONDITION_FAILED - 队列‘my-quorum-queue’的属性‘non-durable’无效

Quorum 队列具有一些特殊功能和限制。它们不能是非持久的,因为 Raft 日志始终写入磁盘,因此它们永远不能被声明为瞬态的。从 3.8.2 开始,它们也不支持消息 TTL 和消息优先级 2。

  1. 仲裁队列的消息默认就是持久化的

对mq熟悉的老铁应该知道,队列的持久化和消息的持久化是分开的。一般情况下如果不对消息声明为持久化的,服务重启之后消息就会丢失。但是仲裁队列默认消息就是持久化的。

下面我手撸了一个简单的demo,同时给经典队列和仲裁队列各发送一条消息。

然后我们重启服务,发现经典队列的消息已经丢失了,但是仲裁队列的消息还在队列中。

仲裁队列 VS 经典队列

数据一致性

仲裁队列使用 Raft 共识算法来确保数据的一致性。即使在单节点情况下,仲裁队列也会严格遵循日志记录和确认机制,确保消息的顺序和一致性。而经典队列在单节点情况下可能会因节点故障导致数据丢失或不一致。

数据可靠性

仲裁队列会将每条消息记录到持久存储中,确保即使在系统崩溃后,消息也不会丢失。经典队列虽然也支持消息持久化,但其可靠性依赖于消息写入磁盘的速度和节点的稳定性。

流式队列(Stream Queues)

流式队列是一种新型队列,专为处理大规模数据流和高吞吐量场景设计。

特点:

  • 存储机制:消息以流的形式存储,可以实现消息的回放和重复消费。

  • 高吞吐量:设计上优化了高吞吐量和低延迟,适合处理大规模实时数据流。

  • 数据持久性:消息可以持久化存储,支持长时间的消息保留和回溯。

  • 订阅机制:支持多种订阅模式,允许多个消费者按需订阅消息流。

什么是消息回放和重复消费?

  • 消息回放:允许消费者在任何时间点重新读取过去的消息。这对于需要重现历史事件或进行审计的应用程序特别有用。

  • 重复消费:消费者可以多次消费同一条消息,这在调试和处理异常时尤为重要。

下面我们通过一个简单的例子看看重复消费

public void InitStreamMQ()
{
    var factory = new ConnectionFactory() { HostName = "localhost", UserName = "user", Password = "myrabbit" };

    var connection = factory.CreateConnection();

    var channel = connection.CreateModel();

    // 声明流式队列

    var args = new Dictionary<string, object> { { "x-queue-type", "stream" } };

    channel.QueueDeclare(queue: "stream_queue", durable: true, exclusive: false, autoDelete: false, arguments: args);

    channel.QueueBind(queue: "stream_queue", exchange: "amq.direct", routingKey: "stream_queue");

}


[ActionTitle(Name = "订阅队列")]
[Route("subscribe")]
public void SubscribeQuorumMessage()
{

    var factory = new ConnectionFactory() { HostName = "localhost", VirtualHost = "/", UserName = "user", Password = "myrabbit" };

    var connection = factory.CreateConnection();

    var channel = connection.CreateModel();

    channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false);

    // 设置消费者,从指定的偏移量消费消息

    var consumer = new EventingBasicConsumer(channel);

    consumer.Received += (model, ea) => {

        var body = ea.Body.ToArray();

        var message = Encoding.UTF8.GetString(body);

        Console.WriteLine(" [x] Received {0}", message);

    };

    /**

     * x-stream-offset的可选值有以下几种:

        first: 从日志队列中第一个可消费的消息开始消费

        last: 消费消息日志中最后一个消息

        next: 相当于不指定offset,消费不到消息。

        Offset: 一个数字型的偏移量

        Timestamp:一个代表时间的Data类型变量,表示从这个时间点开始消费。例如 一个小时前 Date timestamp = new Date(System.currentTimeMillis() - 60 * 60 * 1_000)

     */

    var args = new Dictionary<string, object> { { "x-stream-offset", 2 } };

    channel.BasicConsume(queue: "stream_queue", autoAck: false, arguments: args, consumer: consumer);

}

这里我们往流式队列里面发送了10条消息但是每次消费的时候都从第3条消息(offset为2)开始消费。

流式队列的工作原理

流式队列的工作方式类似于日志系统(如 Apache Kafka)。消息按照顺序追加到队列的末尾,并保存在磁盘上。每个消息都有一个唯一的偏移量(offset),消费者可以通过指定偏移量来读取特定的消息或重新消费消息。

适用场景:

  • 适用于实时数据分析、日志处理、实时监控等场景。

  • 在需要处理大规模数据流和高吞吐量的场景下,流式队列是一个合适的选择。

PS

  1. Auto-Ack 必须为 false

在流式队列中,为了确保消息的可靠性和能够实现消息回放,自动确认(autoAck)必须设置为 false。自动确认会导致消息一旦被消费即刻从队列中移除,失去消息的持久性和回放功能。

  1. 必须设置prefetchCount

流式队列(Stream Queue)在 RabbitMQ 中主要设计用于高吞吐量和低延迟的消息传输。设置 prefetchCount(每次发送给消费者的消息数量)是为了优化流式队列的性能和资源使用。

  1. durable必须设置为true

与Quorum队列类似, Stream队列的durable参数必须声明为true,exclusive参数必须声明为false。这其中,x-max-length-bytes 表示日志文件的最大字节数。x-stream-max-segment-size-bytes 每一个日志文件的最大大小。这两个是可选参数,通常为了防止stream日志无限制累计,都会配合stream队列一起声明。

选型建议

在选择 RabbitMQ 队列类型时,需要根据具体的业务需求和场景来决定。以下是一些选型建议:

  1. 经典队列:

   - 适合大多数常规的消息传递需求。

   - 需要较高的性能和可靠性,但不需要特别高的数据一致性要求。

  1. 仲裁队列:

   - 适用于对数据一致性和高可用性要求较高的场景。

   - 需要确保消息不丢失且能够在多节点间保持数据一致性。

  1. 流式队列:

   - 适合处理大规模实时数据流和高吞吐量的场景。

   - 需要消息的回放和重复消费功能,适用于实时数据分析和日志处理等场景。

总结

通过了解经典队列、仲裁队列和流式队列的特点和应用场景,能够更好地选择适合自己业务需求的队列类型。在实际应用中,可以根据具体的业务需求和性能要求,灵活地选择和配置 RabbitMQ 队列,以实现最佳的消息传递效果。

参考文档

Quorum Queues

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/907886.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【AD】2-1 元件符号的绘制创建实例-电阻容/CHIP类器件

1.新建工程后&#xff0c;双击原理图库&#xff0c;点击Panels后&#xff0c;选择SCH Library&#xff0c;双击元器件可在右侧进行更改名称 2.点击视图&#xff0c;栅格&#xff0c;设置捕捉栅格为100mil 3.点击放置管脚&#xff0c;可按空格键进行旋转&#xff0c;按TAB键可以…

JDBC2(防止sql注入,数据库连接池)

防止SQL注入 sql注入&#xff1a;利用sql语句的语法特点&#xff0c;应用层输入特殊格式&#xff0c;让原有的sql语句失效 创建表结构 并加入数据 create table login(lid int primary key auto_increment,lname varchar(20),lpwd varchar(20),lsex varchar(2),laddr varcha…

基于SSM+微信小程序的订餐管理系统(点餐2)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 基于SSM微信小程序的订餐管理系统实现了管理员和用户。管理端实现了 首页、个人中心、用户管理、菜品分类管理、菜品信息管理、订单信息管理、配送信息管理、菜品评价管理、订单投诉管理、…

MRCTF2020:你传你ma呢

文件上传题先判断黑白名单过滤&#xff0c;先传个最简单的木马 这里上传不了php文件&#xff0c;猜测可能是对php文件进行了过滤&#xff0c;将文件改为任意后缀这里改为.abc 还是上传不成功&#xff0c;猜测可能对MIME也做了过滤&#xff0c;将Content-Type更改为image/jpeg再…

设计模式09-行为型模式2(状态模式/策略模式/Java)

5.4 状态模式 5.4.1 状态模式的定义 1.模式动机&#xff1a;有些对象具有多种状态&#xff0c;这些状态在某些情况下能够相互转换&#xff0c;对象在不同的状态下将具有不同的行为&#xff0c;将拥有状态的对象中和状态的行为分离。 2.模式定义&#xff1a;允许一个对象在其…

tauri中shell的特殊字符

tauri中shell的特殊字符 官网例子&#xff1a;https://tauri.app/plugin/shell/ 中的入参是 \S 入参&#xff0c;但如果入参存在空格等特殊字符串&#xff0c;将无法传入 "permissions": [{"identifier": "shell:allow-execute","allow&qu…

电子电气架构 --- Trace 32(劳特巴赫)多核系统的调试

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所有人的看法和评价都是暂时的,只有自己的经历是伴随一生的,几乎所有的担忧和畏惧,都是来源于自己的想象,只有你真的去做了,才会发现有多快乐。…

使用Web Workers实现JavaScript的多线程编程

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 使用Web Workers实现JavaScript的多线程编程 引言 Web Workers 简介 创建和使用 Worker 通信机制 主线程向 Worker 发送消息 Wor…

【uni-app】创建自定义模板

1. 步骤 打开自定义模板文件夹 在此文件夹下创建模板文件&#xff08;注意后缀名&#xff09; 重新点击“新建页面” 即可看到新建的模板 2. 注意事项 创建的模板必须文件类型对应&#xff08;vue模板就创建*.vue文件, uvue模板就创建*.uvue文件&#xff09;

【云原生】Docker搭建开源翻译组件Deepl使用详解

目录 一、前言 二、微服务项目使用翻译组件的场景 2.1 多语言用户界面 2.2 业务逻辑中的翻译需求 2.3 满足实时通信的要求 2.4 内容管理系统 2.5 个性化推荐系统 2.6 日志和监控 三、开源类翻译组件解决方案 3.1 国内翻译组件方案汇总 3.1.1 百度翻译 3.1.2 腾讯翻…

Hms?: 1渗透测试

靶机&#xff1a;Hms?: 1 Hms?: 1 ~ VulnHub 攻击机&#xff1a;kail linux 2024 主机扫描阶段发现不了靶机&#xff0c;所以需要按DriftingBlues2一样手动配置网卡 1,将两台虚拟机网络连接都改为NAT模式&#xff0c;并查看靶机的MAC地址 2&#xff0c;攻击机上做主机扫描发现…

linux-环境变量

环境变量是系统提供的一组 name value 的变量&#xff0c;不同的变量有不同的用途&#xff0c;通常都具有全局属性 env 查看环境变量 PATH PATH是一个保存着系统指令路径的一个环境变量&#xff0c;系统提供的指令不需要路径&#xff0c;直接就可以使用就是因为指令的路径…

基于Spring Boot的私房菜定制上门服务系统的设计与实现

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统私房菜定制上门服务系统信息管理难度大&#xff0c;容错率…

qt QMenuBar详解

1、概述 QMenuBar是Qt框架中用于创建菜单栏的类&#xff0c;它继承自QWidget。QMenuBar通常位于QMainWindow对象的标题栏下方&#xff0c;用于组织和管理多个QMenu&#xff08;菜单&#xff09;和QAction&#xff08;动作&#xff09;。菜单栏提供了一个水平排列的容器&#x…

转载:【lwip】03-内存管理 - 李柱明 - 博客园

目录 前言3. 内存管理 3.1 内存分配策略 3.1.1 固定大小的内存块3.1.2 可变大小分配3.2 动态内存池&#xff08;pool&#xff09; 3.2.1 介绍3.2.2 内存池的预处理3.2.3 内存池的初始化3.2.4 内存分配3.2.5 内存释放3.2.6 内存池源码定义简要分析 定义内存池资源源码分析保存各…

「Mac畅玩鸿蒙与硬件25」UI互动应用篇2 - 计时器应用实现

本篇将带领你实现一个实用的计时器应用&#xff0c;用户可以启动、暂停或重置计时器。该项目将涉及时间控制、状态管理以及按钮交互&#xff0c;是掌握鸿蒙应用开发的重要步骤。 关键词 UI互动应用时间控制状态管理用户交互 一、功能说明 在这个计时器应用中&#xff0c;用户…

使用MongoDB Atlas构建无服务器数据库

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 使用MongoDB Atlas构建无服务器数据库 MongoDB Atlas 简介 注册账户 创建集群 配置网络 设置数据库用户 连接数据库 设计文档模式…

从零开始的c++之旅——继承

1. 继承 1.继承概念及定义 继承是面向对象编程的三大特点之一&#xff0c;它使得我们可以在原有类特性的基础之上&#xff0c;增加方法 和属性&#xff0c;这样产生的新的类&#xff0c;称为派生类。 继承 呈现了⾯向对象程序设计的层次结构&#xff0c;以前我们接触的…

正向解析和反向解析

正向解析 服务端&#xff1a; [rootlocalhost rhel]# vim /etc/named.conf [rootlocalhost named]# vim /var/named/named.openlab.com 客户端&#xff1a; [rootlocalhost rhel]# nslookup 反向解析 服务端&#xff1a; [rootlocalhost rhel]# vim /etc/named.conf [ro…

计算机网络:网络层 —— 路由信息协议 RIP

文章目录 路由选择协议动态路由协议路由信息协议 RIPRIP 的重要特点RIP的基本工作过程RIP的距离向量算法RIP存在的问题RIP版本和相关报文的封装 路由选择协议 因特网是全球最大的互联网&#xff0c;它所采取的路由选择协议具有以下三个主要特点&#xff1a; 自适应&#xff1a…