【RabbitMQ 实战】11 队列的结构和惰性队列

一、 队列的结构

队列的组成:

  • 队列由 rabbit_amgqueue_process 和 backing_queue两部分组成。
  • rabbit_amqqueue_process负责协议相关的消息处理,即接收生产者发布的消息、向消费者交付消息、处理消息的确认 (包括生产端的 confirm 和消费端的 ack) 等。
  • backing_queue是消息存储的具体形式和引擎,并向rabbit_amqqueue_process提供相关的接口以供调用。
    消息投递:
  • 若消息投递的目的队列是空的,并且有消费者订阅了此队列,则该消息直接发给消费者,不经过队列。
  • 若消息无法直接投递给消费者时,需要暂时将消息存入队列,以便重新投递。消息存入队列后,会随着系统的负载在队列中不断地流动,消息的状态会不断发生变化。

1.1 消息状态分类

消息的4 种状态:

  • alpha状态:表示消息内容 (包括消息体、属性和 headers) 和消息索引都存储在内存中。
  • beta状态:表示消息内容保存在磁盘中,消息索引保存在内存中。
  • gamma状态:表示消息内容保存在磁盘中,消息索引在磁盘和内存中都有。
  • delta状态:表示消息内容和索引都在磁盘中。

注意事项:

  • 对于持久化的消息,消息内容和消息索引都必须先保存在磁盘上,才会处于上述状态中的一种。
  • gamma 状态的消息是只有持久化的消息才会有的状态。

1.2 消息状态对资源影响

rabbitmq在运行时,会根据统计的消息传送速度,定期计算一个当前内存中能够保存的最大消息数量(target_ram_count)。

  • 若alpha 状态的消息数量大于此值时,就会引起消息的状态转换,多余的消息可能会转换到beta 状态、gamma 状态或者 delta 状态。
  • 区分这 4 种状态的主要作用是满足不同的内存和CPU需求。

消息状态对服务器资源的影响:

  • alpha状态最耗内存,但很少消耗 CPU。
  • delta状态基本不消耗内存,但是需要消耗更多的 CPU 和磁盘 I/O 操作。

注意事项:

  • delta 状态需要执行两次I/O 操作才能读取到消息。一次是读消息索引 (从 rabbit_queue_index 中),一次是读消息内容(从 rabbit_msg_store 中)。
  • beta 和 gamma 状态都只需要一次I/0 操作就可以读取到消息 (从 rabbit_msg_store中)。

1.3 队列中的消息状态分布结构

  • 对于普通的没有设置优先级和镜像的队列来说,backing_queue的默认实现是rabbit_variable_queue。其内部通过 5 个子队列 Q1、Q2、Delta、Q3 和 Q4 来体现消息的各个状态。
  • 整个队列包括rabbit_amgqueue_process和backing_queue 的各个子队列。
  • 队列中的消息状态结构分布:
    • Q1、Q4 只包含 alpha 状态的消息。也就是消息体和消息索引都在内存中的消息。
    • Q2 、Q3 包含 beta 和gamma 状态的消息,
    • Delta 只包含 delta 状态的消息。也就是消息内容和索引都在磁盘中的消息。
  • 队列中的消息流动状态变化:
    • 一般情况下,消息按照 Q1——> Q2——> Delta——> Q3——> Q4 顺序进行流动,但并不是每一条消息都一定会经历所有的状态,这个取决于当前系统的负载状况。
    • 从Q1至Q4的过程,就相当于消息内存——> 磁盘——> 内存的过程。
      • 当队列负载高,占用极大的内存时,可以把一部分消息放入磁盘,以此节省内存空间。
      • 当队列负载降低,内存资源释放出来时,这部分消息又渐渐回到内存被消费者获取,使得整个队列具有很好的弹性。
        在这里插入图片描述

1.4 消费者对队列中消息状态的影响变化

消费消息对队列中的消息状态变化流程:

  • 第一步:当消费者获取消息时,首先会从 Q4 中获取内存中消息,如果获取成功则返回。
    若Q4为空,则尝试从 Q3 中获取消息,进入第二步。
  • 第二步:从Q3中获取消息时,系统首先会判断Q3是否为空,如果为空则返回队列为空,即此时队列中无消息。
    若Q3不为空,则取出 Q3 中的消息并和Delta中的消息长度做已判断。如果Q3和Delta都为空,则可以认为 Q2、Delta、03、Q4 全部为空,此时将Q1中的消息直接转移至 Q4,下次直接从Q4 中获取消息。
    若Q3为空,Delta 不为空,则将 Delta 的消息转移至Q3中,下次可以直接从Q3中获取消息。
  • 第三步:在将消息从 Delta 转移到 Q3 的过程中,是按照索引分段读取的,首先读取某一段,然后判断读取的消息的个数与Delta 中消息的个数是否相等,如果相等,则可以判定此时 Delta 中已无消息,则直接将Q2 和刚读取到的消息一并放入到 Q3 中;如果不相等,仅将此次读取到的消息转移到 Q3。

结论:

  • 通常在负载正常时,如果消息被消费的速度不小于接收新消息的速度,对于不需要保证可靠不丢失的消息来说,极有可能只会处于 alpha 状态。
  • 对于 durable 属性设置为 true 的消息一定会进入 gamma 状态,并且在开启 publisher confirm机制时,只有到了 gamma 状态时才会确认该消息已被接收。
  • 若消息消费速度足够快、内存也充足,这些消息也不会继续走到下一个状态。

影响及应对措施:

  • 在系统负载较高时,已接收到的消息若不能很快被消费掉,这些消息就会进入到很深的队列中去,这样会增加处理每个消息的平均开销。因为要花更多的时间和资源处理“堆积”的消息,如此用来处理新流入的消息的能力就会降低,使得后流入的消息又被积压到很深的队列中继续增大处理每个消息的平均开销,继而情况变得越来越恶化,使得系统的处理能力大大降低。
  • 应对这一问题一般有 3 种措施:
    • 增加 prefetch_count值,即一次发送多条消息给消费者,加快消息被消费的速度。这个值跟消息分发有关,开发人员代码中使用设置。
    • 采用 multiple ack,降低处理 ack 带来的开销。可以回顾消费端的确认机制,也是开发人员设置。
    • 流量控制。

二、惰性队列

当生产者将消息发送到RabbitMQ的时候,队列中的消息会尽可能地存储在内存之中,这样可以更加快速地将消息发送给消费者。即使是持久化的消息,在被写入磁盘的同时也会在内存中驻留一份备份。当RabbitMQ需要释放内存的时候,会将内存中的消息换页至磁盘中,这个操作会耗费较长的时间。
惰性队列会将收到的消息直接存入文件系统中,而不管是持久化的或者是非持久化的。这样减少了内存的消耗,但是会增加I/O的使用,如果消息是持久化的,那么这样的I/O操作不可避免。
注意如果惰性队列中存储的是非持久化的消息,内存的使用率会一直很稳定,但是重启后消息一样会丢失。
代码设置惰性队列

在队列声明的时候可以通过x-queue-mode 参数来设置队列的模式,取值为default和lazy。下面示例演示了一个惰性队列的声明细节:

Map<String,Object> args = new HashMap<String,Object>();
args.put( "x-queue-mode" , "lazy");
channel.queueDeclare( "myqueue" , false , false , false , args);

对应的Policy 设置方式为:

rabbitmqctl set_policy Lazy "^myqueue$ " ' {"queue-mode ":" lazy" } ' --apply-to-queues

如果要将普通队列转换为隋性队列,那么我们需要忍受性能损耗,需要将缓存中的消息转存到磁盘中,然后才能接收新的消息。反之,将一个惰性队列转为普通队列,会将磁盘中的消息批量地导入到内存中。

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

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

相关文章

Spring Boot读取配置文件

Spring Boot 是一种用于快速构建基于Spring的应用程序的框架&#xff0c;它提供了很多便利的功能和约定&#xff0c;使开发者可以快速搭建、配置和部署应用程序。在Spring Boot中&#xff0c;读取配置文件是一个非常常见的任务&#xff0c;本文将介绍如何在Spring Boot应用程序…

Qt/C++原创推流工具/支持多种流媒体服务/ZLMediaKit/srs/mediamtx等

一、前言 1.1 功能特点 支持各种本地视频文件和网络视频文件。支持各种网络视频流&#xff0c;网络摄像头&#xff0c;协议包括rtsp、rtmp、http。支持将本地摄像头设备推流&#xff0c;可指定分辨率和帧率等。支持将本地桌面推流&#xff0c;可指定屏幕区域和帧率等。自动启…

CAN通信-应用

up起来 驱动加载完成&#xff0c;使用ifconfig -a 可以看到两个节点 can0: flags128<NOARP> mtu 16unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 10 (UNSPEC)RX packets 0 bytes 0 (0.0 B)RX errors 0 dropped 0 overruns 0 frame 0TX p…

【Vuex+ElementUI】Vuex中取值存值以及异步加载的使用

一、导言 1、引言 Vuex是一个用于Vue.js应用程序的状态管理模式和库。它建立在Vue.js的响应式系统之上&#xff0c;提供了一种集中管理应用程序状态的方式。使用Vuex&#xff0c;您可以将应用程序的状态存储在一个单一的位置&#xff08;即“存储”&#xff09;中&#xff0c;…

MATLAB算法实战应用案例精讲-【图像处理】SLAM技术详解(应用篇)

目录 前言 知识储备 概率论基础 边缘概率 联合概率和独立 独立与条件独立

iPhone15手机拓展坞方案,支持手机快充+传输数据功能

手机拓展坞的组合有何意义&#xff1f;首先是数据存储场景&#xff0c;借助拓展坞扩展出的接口&#xff0c;可以连接U盘、移动硬盘等采用USB接口的设备&#xff0c;实现大文件的快速存储或者流转&#xff1b;其次是图片、视频的读取场景&#xff0c;想要读取相机、无人机SD/TF存…

options.html 页面设计成聊天框,左侧是功能列表,右侧是根据左侧的功能切换成不同的内容。--chatGpt

gpt: 要将 options.html 页面设计成一个聊天框式的界面&#xff0c;其中左侧是功能列表&#xff0c;右侧根据左侧的功能切换成不同的内容&#xff0c;你可以按照以下步骤进行设计和实现&#xff1a; 1. 首先&#xff0c;创建 options.html 文件&#xff0c;并在其中定义基本的…

【Xcode-宏定义配置】

1&#xff0c;项目中配置宏-DEBUG 打开Xcode项目工程 -> Targets -> Build Settings -> Preprocessor Macros -> &#xff0c;在Debug状态下点击右侧&#xff0c;“”添加&#xff0c;在对话框中输入DEBUG1&#xff0c;并保存&#xff0c;注意别把Release给覆盖了…

shell脚本学习

shell是一个用 C 语言编写的程序&#xff0c;是用户使用 Linux 的桥梁。Shell 既是一种命令语言&#xff0c;又是一种程序设计语言。实际上Shell是一个命令解释器&#xff0c;它解释由用户输入的命令并且把它们送到内核。不仅如此&#xff0c;Shell有自己的编程语言用于对命令的…

【angular】实现简单的angular国际化(i18n)

文章目录 目标过程运行参考 目标 实现简单的angular国际化。本博客实现中文版和法语版。 将Hello i18n!变为中文版&#xff1a;你好 i18n!或法语版:Bonjour l’i18n !。 过程 创建一个项目&#xff1a; ng new i18nDemo在集成终端中打开。 添加本地化包&#xff1a; ng a…

042:mapboxGL点击某feature点,使其为中心点

第042个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+mapbox中通过鼠标点击某feature点,让其成为中心点。这里用到了click事件和flyTo的方法。 直接复制下面的 vue+mapbox源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源代码(共113行)相关API参…

spring boot+ vue位置信息大数据综合管理平台源码

spring boot vue位置信息大数据综合管理平台源码 UWB技术的人员定位系统源码 智慧工厂是产业升级的外在表现形式&#xff0c;利用物联网技术加强信息管理的新模式&#xff0c;人员定位管理通过物联网技术、位置信息大数据的综合处理应用&#xff0c;在智慧工厂人员管理方面具有…

大模型之Prompt研究和技巧

大模型之Prompt研究和技巧 大模型之Prompt编写简介组成技术Zero-ShotFew-shotCOTCOT-SCTOTGoTReAct 大模型之Prompt编写 简介 Prompt是是给 AI **模型的指令&#xff0c;**一个简短的文本输入&#xff0c;用于引导AI模型生成特定的回答或执行特定任务。 Prompt是你与语言模型沟…

【方法】PDF不能转换成其它格式如何解决?

想把PDF文件转换成其他格式&#xff0c;比如Word、PPT&#xff0c;却发现无法操作&#xff0c;这是什么情况呢&#xff1f;又该如何解决&#xff1f;下面我们一起来看看吧。 原因1&#xff1a;没有使用PDF编辑器 如果是在线打开PDF&#xff0c;或者使用PDF阅读器打开PDF&…

将 mysql 数据迁移到 clickhouse (最新版)

一、前驱知识 已经在mysql中插入了海量的数据了&#xff0c;这个时候mysql 承载不了这么大的数据&#xff0c;并且数据只需要查询&#xff0c;修改和删除非常少&#xff0c;并且不需要支持事务&#xff0c;这个时候需要换一个底层存储&#xff0c;这里选用的是 clickhouse 来进…

Spring实例化源码解析之ConversionService(十)

前言 ConversionService&#xff08;转换服务&#xff09;是Spring框架中的一个核心接口&#xff0c;用于在不同类型之间进行转换和格式化操作。它提供了一种统一的方式来处理对象之间的类型转换&#xff0c;以及将数据从一种表示形式转换为另一种表示形式。 以下是Conversio…

【论文阅读】面向抽取和理解基于Transformer的自动作文评分模型的隐式评价标准(实验结果部分)

方法 结果 在这一部分&#xff0c;我们展示对于每个模型比较的聚合的统计分析当涉及到计算特征和独立的特征组&#xff08;表格1&#xff09;&#xff0c;抽取功能组和对齐重要功能组&#xff08;表格2&#xff09;&#xff0c;并且最后&#xff0c;我们提供从模型比较&#x…

Linux服务器(银河麒麟、CentOS 7+、CentOS 7+ 等)修改IP地址

打开终端或控制台&#xff0c;以root或具有sudo权限的用户身份登录。根据你的Linux发行版和网络管理工具的不同&#xff0c;相应的命令可能略有不同。使用以下命令编辑网络配置文件&#xff0c;例如eth0网卡的配置文件&#xff1a; 注意&#xff1a;ifcfg-eth0 可能会有不同的命…

解读非托管流动性协议Hover: 差异化、层次化的全新借贷体系

“Hover 是 DeFi 借贷赛道的另辟蹊径者&#xff0c;除了在自身机制&#xff08;借贷模型、治理体系&#xff09;上进行创新获得内生动力外&#xff0c;背靠日渐繁荣的 Kava、Cosmos 生态进一步获得外生动力&#xff0c;发展潜力俱佳” 与 DEX 类似&#xff0c;借贷也是 DeFi 世…

深度学习DAY3:FFNNLM前馈神经网络语言模型

1 神经网络语言模型NNLM的提出 文章&#xff1a;自然语言处理中的语言模型预训练方法&#xff08;ELMo、GPT和BERT&#xff09; https://www.cnblogs.com/robert-dlut/p/9824346.html 语言模型不需要人工标注语料&#xff08;属于自监督模型&#xff09;&#xff0c;所以语言…