RabbitMQ之三种队列之间的区别及如何选型

目录

不同队列之间的区别

Classic经典队列

Quorum仲裁队列

Stream流式队列

如何使用不同类型的队列​

Quorum队列

Stream队列


不同队列之间的区别

Classic经典队列

这是RabbitMQ最为经典的队列类型。在单机环境中,拥有比较高的消息可靠性。

 

       经典队列可以选择是否持久化(Durability)以及是否自动删除(Auto delete)两个属性。其中,Durability有两个选项,Durable和Transient。 Durable表示队列会将消息保存到硬盘,这样消息的安全性更高。但是同时,由于需要有更多的IO操作,所以生产和消费消息的性能,相比Transient会比较低。​ Auto delete属性如果选择为是,那队列将在至少一个消费者已经连接,然后所有的消费者都断开连接后删除自己。Arguments部分,还有非常多的参数,可以点击后面的问号逐步了解。

       在RabbitMQ中,经典队列是一种非常传统的队列结构。消息以FIFO先进先出的方式存入队列。消息被Consumer从队列中取出后就会从队列中删除。如果消息需要重新投递,就需要再次入队。这种队列都依靠各个Broker自己进行管理,在分布式场景下,管理效率是不太高的。并且这种经典队列不适合积累太多的消息。如果队列中积累的消息太多了,会严重影响客户端生产消息以及消费消息的性能。因此,经典队列主要用在数据量比较小,并且生产消息和消费消息的速度比较稳定的业务场景。比如内部系统之间的服务调用。


Quorum仲裁队列

       仲裁队列,是RabbitMQ从3.8.0版本,引入的一个新的队列类型,整个3.8.X版本,也都是在围绕仲裁队列进行完善和优化。仲裁队列相比Classic经典队列,在分布式环境下对消息的可靠性保障更高。官方文档中表示,未来会使用Quorum仲裁队列代替传统Classic队列。

 

       Quorum是基于Raft一致性协议实现的一种新型的分布式消息队列,他实现了持久化,多备份的FIFO队列,主要就是针对RabbitMQ的镜像模式设计的。简单理解就是quorum队列中的消息需要有集群中多半节点同意确认后,才会写入到队列中。这种队列类似于RocketMQ当中的DLedger集群。这种方式可以保证消息在集群内部不会丢失。同时,Quorum是以牺牲很多高级队列特性为代价,来进一步保证消息在分布式环境下的高可靠。从整体功能上来说,Quorum队列是在Classic经典队列的基础上做减法,因此对于RabbitMQ的长期使用者而言,其实是会影响使用体验的。

与普通队列的区别:

        Quorum队列大部分功能都是在Classic队列基础上做减法,比如Non-durable queues表示是非持久化的内存队列。Exclusivity表示独占队列,即表示队列只能由声明该队列的Connection连接来进行使用,包括队列创建、删除、收发消息等,并且独占队列会在声明该队列的Connection断开后自动删除。

       特例Poison Message handling(处理有毒的消息)。所谓毒消息是指消息一直不能被消费者正常消费(可能是由于消费者失败或者消费逻辑有问题等),就会导致消息不断的重新入队,这样这些消息就成为了毒消息。这些读消息应该有保障机制进行标记并及时删除。Quorum队列会持续跟踪消息的失败投递尝试次数,并记录在"x-delivery-count"这样一个头部参数中。然后,就可以通过设置 Delivery limit参数来定制一个毒消息的删除策略。当消息的重复投递次数超过了Delivery limit参数阈值时,RabbitMQ就会删除这些毒消息。当然,如果配置了死信队列的话,就会进入对应的死信队列。  

       Quorum队列更适合于长期存在的队列,并且在对容错、数据安全方面有更严格要求的场景。相对于追求低延迟、非持久化等高级队列,Quorum队列提供了更可靠的数据复制机制,以满足对数据一致性和高可用性的要求。

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


Stream流式队列

​       Stream队列是RabbitMQ自3.9.0版本开始引入的一种新的数据队列类型。这种队列类型的消息是持久化到磁盘并且具备分布式备份的,更适合于消费者多,读消息非常频繁的场景。

       Stream队列的核心是以append-only只添加的日志来记录消息,整体来说,就是消息将以append-only的方式持久化到日志文件中,然后通过调整每个消费者的消费进度offset,来实现消息的多次分发。下方有几个属性也都是来定义日志文件的大小以及保存时间。如果你熟悉Kafka或者RocketMQ,会对这种日志记录消息的方式非常熟悉。这种队列提供了RabbitMQ已有的其他队列类型不太好实现的四个特点:

large fan-outs 大规模分发
       
当想要向多个订阅者发送相同的消息时,以往的队列类型必须为每个消费者绑定一个专用的队列。如果消费者的数量很大,这就会导致性能低下。而Stream队列允许任意数量的消费者使用同一个队列的消息,从而消除绑定多个队列的需求。
Replay/Time-travelling 消息回溯
​       RabbitMQ已有的这些队列类型,在消费者处理完消息后,消息都会从队列中删除,因此,无法重新读取已经消费过的消息。而Stream队列允许用户在日志的任何一个连接点开始重新读取数据。
Throughput Performance 高吞吐性能
​        Strem队列的设计以性能为主要目标,对消息传递吞吐量的提升非常明显。
Large logs 大日志
​       RabbitMQ一直以来有一个让人诟病的地方,就是当队列中积累的消息过多时,性能下降会非常明显。但是Stream队列的设计目标就是以最小的内存开销高效地存储大量的数据。使用Stream队列可以比较轻松的在队列中积累百万级别的消息。

       整体上来说,RabbitMQ的Stream队列,其实有很多地方借鉴了其他MQ产品的优点,在保证消息可靠性的基础上,着力提高队列的消息吞吐量以及消息转发性能。因此,Stream也是在视图解决一个RabbitMQ一直以来,让人诟病的缺点,就是当队列中积累的消息过多时,性能下降会非常明显的问题。RabbitMQ以往更专注于企业级的内部使用,但是从这些队列功能可以看到,Rabbitmq也在向更复杂的互联网环境靠拢,未来对于RabbitMQ的了解,也需要随着版本推进,不断更新。


如何使用不同类型的队列​

这几种不同类型的队列,虽然实现方式各有不同,但是本质上都是一种存储消息的数据结构。

Quorum队列

      Quorum队列与Classic队列的使用方式是差不多的。最主要的差别就是在声明队列时有点不同。如果要声明一个Quorum队列,则只需要在后面的arguments中传入一个参数,x-queue-type,参数值设定为quorum

Map<String,Object> params = new HashMap<>();
params.put("x-queue-type","quorum");
//声明Quorum队列的方式就是添加一个x-queue-type参数,指定为quorum。默认是classic
channel.queueDeclare(QUEUE_NAME, true, false, false, params);

       Quorum队列的消息是必须持久化的,所以durable参数必须设定为true,如果声明为false,就会报错。同样,exclusive参数必须设置为false。这些声明,在Producer和Consumer中是要保持一致的。

Stream队列

​        Stream队列相比于Classic队列,在使用上就要稍微复杂一点。如果要声明一个Stream队列,则 x-queue-type参数要设置为 stream 。

        Map<String,Object> params = new HashMap<>();params.put("x-queue-type","stream");params.put("x-max-length-bytes", 20_000_000_000L); // maximum stream size: 20 GBparams.put("x-stream-max-segment-size-bytes", 100_000_000); // size of segment files: 100 MBchannel.queueDeclare(QUEUE_NAME, true, false, false, params);

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

当要消费Stream队列时,要重点注意他的三个必要的步骤:

1. channel必须设置basicQos属性。 与Spring框架集成使用时,channel对象可以在@RabbitListener声明的消费者方法中直接引用,Spring框架会进行注入。

2. 正确声明Stream队列。 在Queue对象中传入声明Stream队列所需要的参数。

3. 消费时需要指定offset。 与Spring框架集成时,可以通过注入Channel对象,使用原生API传入offset属性。

       例如用原生API创建Stream类型的Consumer时,还必须添加一个参数x-stream-offset,表示从队列的哪个位置开始消费。  

 	Map<String,Object> consumeParam = new HashMap<>();consumeParam.put("x-stream-offset","last");channel.basicConsume(QUEUE_NAME, false,consumeParam, myconsumer);

x-stream-offset的可选值有以下几种:
first: 从日志队列中第一个可消费的消息开始消费
last: 消费消息日志中最后一个消息
next: 相当于不指定offset,消费不到消息。
Offset: 一个数字型的偏移量
Timestamp:一个代表时间的Data类型变量,表示从这个时间点开始消费。例如 一个小时前 Date timestamp = new Date(System.currentTimeMillis() - 60 * 60 * 1_000)

       由于在Consumer中必须传入x-stream-offset这个参数,所以在与SpringBoot集成时,stream队列目前暂时无法正常消费。在目前版本下,使用RabbitMQ的SpringBoot框架集成,可以正常声明Stream队列,往Stream队列发送消息,但是无法直接消费Stream队列了。

       SpringBoot框架集成RabbitMQ后,为了简化编程模型,就把channel,connection等这些关键对象给隐藏了,目前框架下,无法直接接入这些对象的注入过程,所以无法直接使用。

       如果非要使用Stream队列,那么有两种方式,一种是使用原生API的方式,在SpringBoot框架下自行封装。另一种是使用RabbitMQ的Stream 插件。在服务端通过Strem插件打开TCP连接接口,并配合单独提供的Stream客户端使用。这种方式对应用端的影响太重了,并且并没有提供与SpringBoot框架的集成,还需要自行完善,因此Stream队列使用较少。 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据库管理-第141期 DG PDB - Oracle DB 23c(20240129)

数据库管理141期 2024-01-29 第141期 DG PDB - Oracle DB 23c&#xff08;20240129&#xff09;1 概念2 环境说明3 操作3.1 数据库配置3.2 配置tnsname3.3 配置强制日志3.4 DG配置3.5 DG配置建立联系3.6 启用所有DG配置3.7 启用DG PDB3.8 创建源PDB的DG配置3.9 拷贝pdbprod1文件…

2023年算法CDO-CNN-BiLSTM-ATTENTION回归预测(matlab)

2023年算法CDO-CNN-BiLSTM-ATTENTION回归预测&#xff08;matlab&#xff09; CDO-CNN-BiLSTM-Attention切诺贝利灾难优化器优化卷积-长短期记忆神经网络结合注意力机制的数据回归预测 Matlab语言。 切诺贝利灾难优化器Chernobyl Disaster Optimizer (CDO)是H. Shehadeh于202…

薅运营商羊毛?封杀!

最近边小缘在蓝点网上看到一则消息 “浙江联通也开始严格排查PCDN和PT等大流量行为 被检测到可能会封停宽带”。 此前中国联通已经在四川和上海等多个省市严查家庭宽带 (部分企业宽带也被查) 使用 PCDN 或 PT&#xff0c;当用户的宽带账户存在大量上传数据的情况&#xff0c;中…

Jupyter notebook文件默认存储路径以及更改方法

目录 1、文件默认存储路径怎么查&#xff1f;2、文件默认存储路径怎么改&#xff1f; 转自&#xff1a;https://blog.csdn.net/fengyeer20120/article/details/109483362 初次使用Jupyter Notebook&#xff0c;确实好用啊&#xff01;但安装Anaconda后&#xff0c;打开Jupyter …

cocos creator 调用预设体Prefab中的方法(调用另一个节点的方法)

调用预设体中的方法 通过cc.instantiate(this.star)创建这个预设体实例这个star预设体中添加了一个脚本组件star.ts 获取到这个脚本组件star.getComponent(‘star’).test()&#xff0c;并调用其中的test()方法同理可以用该方式像另一个节点中传值 //星星预设体property(cc.Pr…

【动态规划】【图论】【C++算法】1575统计所有可行路径

作者推荐 【动态规划】【字符串】【行程码】1531. 压缩字符串 本文涉及知识点 动态规划汇总 图论 LeetCode1575统计所有可行路径 给你一个 互不相同 的整数数组&#xff0c;其中 locations[i] 表示第 i 个城市的位置。同时给你 start&#xff0c;finish 和 fuel 分别表示出…

RK3568 Android 13 系统裁剪

android 13 系统裁剪是个大工程&#xff0c;裁剪也是需要大量的测试&#xff0c;才能保证系统的稳定性&#xff0c;以下是RK官方给出的裁剪方案&#xff0c;有兴趣的可以去看一下&#xff0c;对裁剪不是要求过高的可以根据官方的建议&#xff0c;对系统进行裁剪: Rockchip And…

Web开发8:前后端分离开发

在现代的 Web 开发中&#xff0c;前后端分离开发已经成为了一种常见的架构模式。它的优势在于前端和后端可以独立开发&#xff0c;互不干扰&#xff0c;同时也提供了更好的可扩展性和灵活性。本篇博客将介绍前后端分离开发的概念、优势以及如何实现。 什么是前后端分离开发&am…

Spring 学习1

1、什么是Spring Spring 是一款主流的 Java EE 轻量级开源框架 &#xff0c;Spring 由“Spring 之父”Rod Johnson 提出并创立&#xff0c;其目的是用于简化 Java 企业级应用的开发难度和开发周期。Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言…

5G安卓核心板开发板_MT6833天玑700规格参数

核心板采用沉金生产工艺&#xff0c;耐腐蚀抗干扰&#xff0c;支持-20℃-70℃环境下7x24小时稳定运行&#xff0c;尺寸仅为45mmx48mm x2.65mm&#xff0c;可嵌入到各种智能产品中&#xff0c;助力智能产品便携化及功能差异化。 联发科MT6833处理器采用台积电 7nm 制程的5G SoC…

vue3 el-pagination 将组件中英文‘goto’ 修改 为 中文到‘第几’

效果如图&#xff1a; 要求&#xff1a;将英文中Go to 改为到第几 操作如下&#xff1a; <template><div class"paging"><el-config-provider :locale"zhCn"> // 注意&#xff1a;这是重要部分<el-pagination //分页组件根据官…

【寒假每日一题·2024】AcWing 5415. 仓库规划(补)

文章目录 一、题目1、原题链接2、题目描述 二、解题报告1、思路分析2、时间复杂度3、代码详解 一、题目 1、原题链接 5415. 仓库规划 2、题目描述 二、解题报告 1、思路分析 思路参考y总&#xff1a;y总讲解视频 &#xff08;1&#xff09;由于每一个仓库均有一个m维向量的位…

非阿里云注册域名如何在云解析DNS设置解析?

概述 非阿里云注册域名使用云解析DNS&#xff0c;按照如下步骤&#xff1a; 添加域名。 添加解析记录。 修改DNS服务器。 DNS服务器变更全球同步&#xff0c;等待48小时。 添加解析记录 登录云解析DNS产品控制台。 在 域名解析 页面中&#xff0c;单击 添加域名 。 在 …

Qt/C++音视频开发64-共享解码线程/重复利用解码/极低CPU占用/画面同步/进度同步

一、前言 共享解码线程主要是为了降低CPU占用&#xff0c;重复利用解码&#xff0c;毕竟在一个监控系统中&#xff0c;很可能打开了同一个地址&#xff0c;需要在多个不同的窗口中播放&#xff0c;形成多屏渲染的效果&#xff0c;做到真正的完全的画面同步&#xff0c;在主解码…

Linux:共享内存

文章目录 System V共享内存的原理管理共享内存shmgetshmatshmdtshmctl 共享内存和管道实现进程间同步通信 前面介绍完了匿名管道和命名管道&#xff0c;那么本篇要引入的主题是共享内存 System V 作为进程通信部分的内容&#xff0c;共享内存必然有其存在的意义和价值&#x…

【C/C++ 01】初级排序算法

排序算法通常是针对数组或链表进行排序&#xff0c;在C语言中&#xff0c;需要手写排序算法完成对数据的排序&#xff0c;排序规则通常为升序或降序&#xff08;本文默认为升序&#xff09;&#xff0c;在C中&#xff0c;<algorithm>头文件中已经封装了基于快排算法的 st…

51单片机通过级联74HC595实现倒计时秒表Protues仿真设计

一、设计背景 近年来随着科技的飞速发展&#xff0c;单片机的应用正在不断的走向深入。本文阐述了51单片机通过级联74HC595实现倒计时秒表设计&#xff0c;倒计时精度达0.05s&#xff0c;解决了传统的由于倒计时精度不够造成的误差和不公平性&#xff0c;是各种体育竞赛的必备设…

光学3D表面轮廓仪服务超精密抛光技术发展

随着技术的不断进步&#xff0c;精密制造领域对材料表面的处理要求越来越高&#xff0c;超精密抛光技术作为当下表面处理的尖端技术&#xff0c;对各种高精密产品的生产起到了至关重要的作用&#xff0c;已广泛应用于集成电路制造、医疗器械、航空航天、3C电子、汽车、精密模具…

Flutter 高级动画技术综合指南

在动画领域&#xff0c;Flutter 提供了一系列功能&#xff0c;包括基于物理的动画&#xff0c;可以模拟真实世界的动态&#xff0c;在应用程序中创建更逼真和自然的运动。 本文将深入研究 Flutter 动画&#xff0c;探索各种类型&#xff0c;并演示如何在项目中实现它们。 Flu…

Linux系统Shell脚本-----------正则表达式 、grep、 sed

一、正则表达式 1.前言 正则表达式(regular expression)描述了一种字符串匹配的模式&#xff08;pattern&#xff09;&#xff0c;可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。在Linux中也就是代表我们定义的模式模板&…