当前位置: 首页 > news >正文

详解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

相关文章:

详解RabbitMQ三种队列类型

RabbitMQ 是一个强大的消息队列系统&#xff0c;它提供了多种队列类型以满足不同的使用需求。本文将探讨三种主要队列类型&#xff1a;经典队列、仲裁队列和流式队列&#xff0c;并讨论它们的区别和选型建议。 经典队列&#xff08;Classic Queues&#xff09; 简介&#xff…...

openGauss数据库-头歌实验1-3 创建和管理模式

一、创建和使用模式 &#xff08;一&#xff09;任务描述 本关任务&#xff1a;基于 openGauss 学习创建模式的相关知识。 &#xff08;二&#xff09;相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;1.openGauss 的常用操作&#xff0c;2.SQL 创建模式相关语…...

森林火灾检测数据集(猫脸码客 第233期)

森林火灾检测数据集 森林火灾是一种具有巨大破坏性的自然灾害&#xff0c;每年在全球范围内造成巨大损失。为了有效应对森林火灾&#xff0c;及早发现和快速响应是至关重要的。传统上&#xff0c;森林火灾的检测主要依赖于人工巡逻和卫星遥感技术。然而&#xff0c;这些方法存…...

LeetCode100之找到字符串中所有字母异位词(438)--Java

1.问题描述 给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺序。 示例1 输入: s "cbaebabacd", p "abc" 输出: [0,6] 解释: 起始索引等于 0 的子串是 "cba", 它是 …...

【Python】Python自习课:第一个python程序

【Python】Python自习课&#xff1a;第一个python程序...

DICOM标准:解析DICOM属性中的病人模块

目录 病人模块概述 1. 病人关系模块&#xff08;Patient Relationship Module&#xff09; 2. 病人识别模块&#xff08;Patient Identification Module&#xff09; 3. 病人统计模块&#xff08;Patient Demographic Module&#xff09; 4. 病人医学模块&#xff08;Pati…...

C++设计模式创建型模式———生成器模式

文章目录 一、引言二、生成器/建造者模式三、总结 一、引言 上一篇文章我们介绍了工厂模式&#xff0c;工厂模式的主要特点是生成对象。当对象较简单时&#xff0c;可以使用简单工厂模式或工厂模式&#xff1b;而当对象相对复杂时&#xff0c;则可以选择使用抽象工厂模式。 工…...

基于微信小程序的校园失物招领系统的研究与实现(V4.0)

博主介绍&#xff1a;✌stormjun、8年大厂程序员经历。全网粉丝15w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&…...

DDRNet模型创新实现人像分割

项目源码获取方式见文章末尾&#xff01; 600多个深度学习项目资料&#xff0c;快来加入社群一起学习吧。 《------往期经典推荐------》 项目名称 1.【BiLSTM模型实现电力数据预测】 2.【卫星图像道路检测DeepLabV3Plus模型】 3.【GAN模型实现二次元头像生成】 4.【CNN模型实…...

try…catch…finally语句里return语句的执行顺序是怎样的?

第一种情况 try语句块里面有return语句&#xff0c;catch语句块和finally语句块里面没有return语句。 代码如下&#xff1a; public class Main {public static void main(String[] args) {System.out.println(test1());}public static int test1() {int i 10;try {System.o…...

AIGC与虚拟现实(VR)的结合与应用前景

公主请阅 引言1. AIGC与VR的基本概念1.1 AIGC简介1.2 VR技术概述 2. AIGC在VR中的应用2.1 生成虚拟环境2.2 自动生成内容2.3 互动体验 3. AIGC与VR结合的应用案例3.1 教育培训3.2 娱乐与游戏3.3 心理治疗3.4 虚拟旅游 4. AIGC与VR结合的挑战4.1 技术限制4.2 用户体验4.3 数据隐…...

如何在visual studio中 生成 并 使用dll和lib文件

因为工作需求&#xff0c;要写lib和dll给别人使用。 使用visual studio2022 以函数 int getmyset() { return 0;} 为例子 首先 点击打开 visual studio 文件->新建->项目 选择windows桌面向导 选择应用程序类型为动态链接库.dll 分别创建MyDLL.h和MyDLL.cpp文件&a…...

「Mac畅玩鸿蒙与硬件15」鸿蒙UI组件篇5 - Slider 和 Progress 组件

Slider 和 Progress 是鸿蒙系统中的常用 UI 组件。Slider 控制数值输入,如音量调节;Progress 显示任务的完成状态,如下载进度。本文通过代码示例展示如何使用这些组件,并涵盖 进度条类型介绍、节流优化、状态同步 和 定时器动态更新。 关键词 Slider 组件Progress 组件节流…...

Iceoryx2:高性能进程间通信框架(中间件)

文章目录 0. 引言1. 主要改进2. Iceoryx2 的架构3. C示例代码3.1 发布者示例&#xff08;publisher.cpp&#xff09;3.2 订阅者示例&#xff08;subscriber.cpp&#xff09; 4. 机制比较5. 架构比较6. Iceoryx vs Iceoryx2参考资料 0. 引言 Iceoryx2 是一个基于 Rust 实现的开…...

构 造 器

我们创建了一个对象&#xff0c;在其中定义了属性&#xff0c;new一个对象&#xff0c;然后设置对应的属性&#xff0c;但是我们可以在new对象的时候&#xff0c;同时传入我们要设置的属性&#xff0c;这个时候就需要构造器。 特点 构造方法是一个特殊的成员方法&#xff0c;…...

草莓叶片病害识别与分类数据集(猫脸码客 第234期)

草莓叶片病害识别与分类数据集 草莓作为一种重要的经济作物&#xff0c;在全球范围内广泛种植。然而&#xff0c;草莓生产过程中常常受到各种病害的困扰&#xff0c;其中叶片病害尤为严重。为了有效识别、检测和分类草莓叶片病害&#xff0c;构建一个高质量的数据集是至关重要…...

微服务设计模式 - 断路器模式 (Circuit Breaker Pattern)

微服务设计模式 - 断路器模式 (Circuit Breaker Pattern) 定义 断路器模式&#xff08;Circuit Breaker Pattern&#xff09;是云计算和微服务架构中的一种保护性设计模式&#xff0c;其目的是避免系统中的调用链出现故障时&#xff0c;导致系统瘫痪。通过断路器模式&#xff…...

HarmonyOS NEXT 应用开发实战(九、知乎日报项目详情页实现详细介绍)

在本篇博文中&#xff0c;我们将探讨如何使用 HarmonyOS Next 框架开发一个知乎日报的详情页&#xff0c;逐步介绍所用到的组件及代码实现。知乎日报是个小巧完整的小项目&#xff0c;这是一个循序渐进的过程&#xff0c;适合初学者和有一定开发经验的工程师参考。 1. 项目背景…...

lvgl 模拟器移植(V9)

1.模拟器代码下载 1.1&#xff1a;通过git 下载 github链接&#xff1a;GitHub - lvgl/lv_port_pc_visual_studio: Visual Studio projects for LVGL embedded graphics library. Recommended on Windows. Linux support with Wayland is work in progress.https://github.com…...

基于vue+neo4j 的中药方剂知识图谱可视化系统

前言 历时一周时间&#xff0c;中药大数据R02系统中药开发完毕&#xff0c;该系统通过scrapy工程获取中药数据&#xff0c;使用python pandas预处理数据生成知识图谱和其他相关数据&#xff0c;利用vuespringbootneo4jmysql 开发系统&#xff0c;具体功能请看本文介绍。 简要…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

剑指offer20_链表中环的入口节点

链表中环的入口节点 给定一个链表&#xff0c;若其中包含环&#xff0c;则输出环的入口节点。 若其中不包含环&#xff0c;则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

Java面试专项一-准备篇

一、企业简历筛选规则 一般企业的简历筛选流程&#xff1a;首先由HR先筛选一部分简历后&#xff0c;在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如&#xff1a;Boss直聘&#xff08;招聘方平台&#xff09; 直接按照条件进行筛选 例如&#xff1a…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)

参考官方文档&#xff1a;https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java&#xff08;供 Kotlin 使用&#xff09; 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

Python 实现 Web 静态服务器(HTTP 协议)

目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1&#xff09;下载安装包2&#xff09;配置环境变量3&#xff09;安装镜像4&#xff09;node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1&#xff09;使用 http-server2&#xff09;详解 …...

论文阅读:Matting by Generation

今天介绍一篇关于 matting 抠图的文章&#xff0c;抠图也算是计算机视觉里面非常经典的一个任务了。从早期的经典算法到如今的深度学习算法&#xff0c;已经有很多的工作和这个任务相关。这两年 diffusion 模型很火&#xff0c;大家又开始用 diffusion 模型做各种 CV 任务了&am…...

DAY 26 函数专题1

函数定义与参数知识点回顾&#xff1a;1. 函数的定义2. 变量作用域&#xff1a;局部变量和全局变量3. 函数的参数类型&#xff1a;位置参数、默认参数、不定参数4. 传递参数的手段&#xff1a;关键词参数5 题目1&#xff1a;计算圆的面积 任务&#xff1a; 编写一…...

sshd代码修改banner

sshd服务连接之后会收到字符串&#xff1a; SSH-2.0-OpenSSH_9.5 容易被hacker识别此服务为sshd服务。 是否可以通过修改此banner达到让人无法识别此服务的目的呢&#xff1f; 不能。因为这是写的SSH的协议中的。 也就是协议规定了banner必须这么写。 SSH- 开头&#xff0c…...