消息队列 - RabbitMQ - 拓展

news2024/11/15 23:19:27

1. Message 状态

Message 在投递时,如果当前 Queue 没有 Message,且有 Consumer 已经订阅了这个 Queue,那么该 Message 会直接发送给 Consumer,不会经过 Queue 存储 Message 的这一步

当 Message 无法直接投递给 Consumer 时,Message 会存储在 Queue 中;在 RabbitMQ 中,Queue 中存储的 Message 有4种状态,且 Message 随着系统的变化而不断更新自己的状态


四种状态:

  • alpha:消息索引和消息内容都存在内存中
  • beta:消息索引存内存,消息内存存磁盘
  • gama:消息索引内存和磁盘都有,消息内容存磁盘
  • delta:消息索引和内容都存磁盘

alpha 状态:由于所有的东西都保存在内存中,所以这种状态下最消耗内存
delta 状态:由于所有的东西都保存在磁盘中,也就意味着在读取消息时,每次都要进行 I/O 操作;在这种状态下,最消耗 CPU 中的资源
gama 状态:只有持久化消息才会有该种状态

RabbitMQ 会根据负载和 Message 传递的速度,定期的计算在内存中可以存放 Message 的最大数量,当 alpha 状态的 Message 超过计算的最大数量时,就会引起状态的变化

2. 惰性队列

2.1 简介

惰性队列尽可能地将消息存入磁盘中,并在消费者消费到相应的消息的时候才会被加载到内存中

默认情况下,当 Producer 将 Message 发送到 RabbitMQ 的时候,Queue 中的 Message 会尽可能地存在内存中,这样可以更快的将 Message 发送给 Consumer,即便是持久化消息也会在内存中保持一个副本
而当 RabbitMQ 所占用的内存超过限额时,就需要释放内存,此时会将内存中保存的 Message 写到磁盘中;在这个过程中,队列将无法接收到新的消息

而对于惰性队列来说,接收到 Message 之后,会直接将其写入磁盘中,不管此条 Message 是持久化还是非持久化。在使用惰性队列时,会降低内存的消耗,但是不可避免的是频繁的 I/O 操作
但是要注意的是,惰性队列如果存储非持久化的消息,重启后会丢失

当 Message 是持久化消息时,更适合惰性队列
也适合于消费者不能正常消息 还能保证消息接收的吞吐量的场景

2.2 与普通队列对比

普通队列占用内存较多,惰性队列占用内存较少

当对于相同的大量消息来对比的话,惰性队列的耗时会比普通队列的要少。因为普通队列当消息过多的存储在内存中时,会触发将消息写入磁盘的动作。上面有提到,当内存不足,消息写入磁盘时,队列会阻塞

3. 警告和流控

当内存占用超过配置的值或磁盘剩余空间低于配置的值时,RabbitMQ 会暂时阻塞所有 Producer 的连接,并停止接收 Producer 发来的消息,以免服务崩溃。与此同时客户端与服务端的心跳检测也会失效


心跳检测:用来检测通信的对端是否存活
当客户端与 RabbitMQ 之间一段时间没有进行交互,那么服务器将会自动断开与客户端之间的 TCP 连接;心跳检测就是用于检测当前的 TCP 连接是否还在进行交互
其原理是,向客户端发送一个心跳检测包,如果在一段时间内没有回应的话,那么就会断掉本次的 TCP 链接


心跳检测实际上是启用两个进程,分别检测两种情况:

  • 定时检测 TCP 连接上是否有数据发送
    如果在一段时间内没有数据发送给客户端,则会发送一个心跳包给客户端,然后循环进行下一次检测
  • 定时检测 TCP 连接上是否有数据接收
    如果一段时间内没有收到任何数据,则判定为心跳超时,最终会关闭 TCP 连接

3.1 内存警告

在默认情况下,当内存低于40%的时候,RabbitMQ 中的所有 Producer 就会停止发送消息,然后触发将内存中的消息写进磁盘的动作,从而释放内存空间

3.2 磁盘警告

默认情况下,当磁盘剩余空间低于50M的时候,RabbitMQ 会阻塞所有的 Producer ,同时停止将内存中的消息写进磁盘的操作

磁盘空间的检查频率并不是固定的,他会随着上一次的检查结果而变化
当检测到上一次的剩余空间接近临界值时,那么检查的频率会加快,反之

3.3 流量控制

上面的内存警告和磁盘警告中,当低于阈值时发生的动作是针对所有的 Connection 做出的处理;而流量控制是针对单个 Connection

流量控制用来避免消息发送过快而导致服务器难以处理的情况


Connection 在 RabbitMQ 中存在5种状态:

  • running:运行中
  • flow:流控
  • idle:空闲
  • blocked:阻塞
  • unblocked:未阻塞

当 Connection 的状态为 flow 时,意味着 Connection 的状态在 blocked 和 unblocked 中来回切换
flow 状态其实和 running 状态较大的区别其实只有他们的发送效率

4. 镜像(Mirror)队列

4.1 背景

在现在的高并发场景中,队列一般都是以集群的方式来部署的;但是如果集群中只存在一个 Broker 节点的话,该节点一旦失效,将会导致整体服务也不可用,且会造成消息的丢失

此时应该会有人想到,如果消息都是持久化的消息,是不是当节点失效时,也不会导致消息的丢失呢?
其实不是的,的确是可以将消息设置为可持久化消息,但是在上一篇关于 RabbitMQ 的文章有说过,写入文件的操作不是立刻执行的,具体的触发条件在上一篇文章已经说过,此处不再赘述。在消息发送之后,接着写入磁盘会有一定的时间间隔,我们称其为“时间窗”。如果在这个时间窗内节点发送故障,那么也会导致消息的丢失

所以引入镜像队列,将队列镜像到其他节点上。此时如果集群中一个节点不可用之后,队列会自动切换到另一个镜像队列上,保证服务的可用

在镜像队列的使用中,对每一个配置了镜像的队列都会包含一个主节点(master)和多个从节点(slave)

4.2 工作原理

当消息发送到配置了镜像的队列时,消息会同时往自己的 slave 节点进行同步
如果因为某些原因,master 变成不可用,但是因为消息同步给了 slave ,所以消息并不会丢失,只需等待其中的一个 slave 节点被推举为 master 之后,服务将会重新变成可用

推举的规则也很简单,哪一个 slave 存在的时间最长,那么就会推举他为新的 master

配置了镜像的队列,其发布确认机制也会和普通的队列不同。镜像队列要所有的节点都发送了确认消息之后,才真正的算“确认”

要注意的是,虽然是配置了 slave ,但是平常的所有读写工作,也都是由 master 来完成,slave 只做一个备份数据的工作。哪怕是有 TCP 与 slave 建立了链接,slave 也不会直接对其进行处理,而是将请求做一个转发的动作,让 master 来完成本次链接的请求

如果在一个已存在的镜像队列中添加一个新的节点,默认情况下,新的节点不会接收到数据的同步
除非服务器显示的调用同步数据的命令,那么此时所有的队列都会进入阻塞状态,等待数据同步完给新的节点时,才会恢复正常

在镜像队列启动的时候,也是 master 先启动;如果是 slave 先启动的话,slave 会进入等待状态,如果在指定时间内发现 master 没有启动,那么已经启动的 slave 会自动停止。这个原理只要大家玩过集群,我想应该都会知道的

4.3 宕机原理

当 slave 挂掉之后,与该 slave 相连的客户端全部断开之外,不会有其他的影响


当 master 挂掉之后,会进行如下动作:

  • 与 master 的全部客户端断开
  • 选举存活时间最长的 slave 作为新的 master,如果此时 slave 未同步,那么未同步的消息会丢失
  • 新的 master 重新入队所有未确认的消息,因为可能 master 未能同步已确认的消息,所以有些消息会被重复消费

4.4 架构图

在这里插入图片描述

5. 仲裁(Quorum)队列

5.1 背景

RabbitMQ 3.8 版本中的重要特性
在 3.8 版本之前,实现高可用队列的方式只有上面的镜像队列

镜像队列其实解决的问题是:消息同步,其实实现的过程,简单的说就是将消息从 master 复制一份去 slave

但是有没有想过一个问题:一个节点宕机,然后一段时间之后,该节点重新上线,重新上线的节点以前的所有数据都会丢失;此时会面临一个问题,我们要不要将数据重新同步到该队列中?
如果同步的话,同步的过程中,所有的队列都会处于阻塞状态,此时就会堆积大量的消息
如果不同步的话,仅仅让新的消息复制到这个重新上线的队列中,老的消息不进行同步;那么当现在的 master 宕机之后,该队列没有同步所有的消息,会增加消息丢失的风险

而仲裁队列的出现,旨在解决镜像队列之间的性能和同步问题

5.2 工作原理

每个仲裁队列都有多个副本,其中包含一个主副本和多个从副本
每个副本都在不同的 RabbitMQ 节点上

和镜像队列一样,生产者和消费者都只会和主副本进行交互,从副本仅仅作为一个数据的备份
在主副本所在的节点宕机后,在另外节点的从副本才会被选举为新的主副本,然后继续提供服务

之所以叫做仲裁队列,是因为消息的同步和主副本的选举,都要超过半数的副本同意
当生产者发送一条消息的时候,要超过半数的副本将消息写入磁盘以后,才会向生产者发送确认信号;这也意味着,有些比较慢的副本不会影响整个队列的速度

为什么说仲裁队列解决了镜像队列的同步问题?
细心的人应该有看见,副本是将消息写入磁盘的,也就是说,仲裁队列中的消息都是持久化的;当节点重新上线时,直接从上次中断的地方开始在磁盘中复制消息,且复制的过程是非阻塞的。而镜像队列中的消息因为不全是持久化的消息,所以才会出现不同步的问题

要注意的是,如果超过半数的副本丢失,那么队列的数据就代表永久丢失;虽然还存在一些副本,但是队列是没有办法恢复的,只能被强制删除

5.3 带来的问题

5.3.1 磁盘使用

如果有一条消息是要投递到多个队列中,比如使用的交换机的主题交换机或扇形交换机:

普通的队列只会将消息在磁盘中存储一次,其他的队列只会保存这条消息的引用;也就是说,只会对磁盘进行一次写入操作
而在仲裁队列中,每个副本都会将这条消息写入磁盘;也就是说,有多少个副本,就会对磁盘进行多少次的写入操作

所以,在仲裁队列的使用中,要注意磁盘的写入次数,因为 IO 的操作是很消耗性能的
在这个例子中,也可以看出,仲裁队列并不适合与扇形交换机一起使用

5.3.2 内存使用

仲裁队列中的消息虽然都是持久化的,但是所有的消息也会一直保存在内存中
如果不及时的进行消费,内存会一直处于负荷状态,可能会导致生产者停止工作

6. 死信(Dead-Letter)队列

6.1 简介

“死信”:其实也是消息的一种,只不过满足了一些条件之后的一种称呼

消息变成死信,有如下三种情况:

  • 消息被拒绝消费
  • 消息过期
  • 队列达到了最大长度

当消息满足上面的三种条件的其中一种之后,消息就会被定义成“死信”,然后被重新发送到另一个交换机中,这个交换机也被叫做“死信交换机(DLX)”,用于绑定的队列,也被称之为“死信队列
DLX 与其他正常的交换机没有什么区别,只是用于存放一些 “死信“

其设计目的是为了存储没有被正常消费的消息,便于排查和重新投递

6.2 架构图

在这里插入图片描述

7. 延时(Delay)队列

7.1 简介

延时队列存储的是延时消息

不是所有的消息在发送之后,都需要立刻被消费的,要看具体的使用场景
举个很常见的例子:淘宝下单,大家应该都有那种下单之后,但是没有支付,然后跳转到另一个界面;界面里有个倒计时,显示请在多少分钟内完成支付
这其实就是一种延时处理消息的例子

当向延时队列添加元素的时候,会给元素设置上一个延迟时间(Delay)
队列会根据延迟时间作为排序条件,较小的元素会优先放在队列的首部
队列中的元素只有到了设置的延迟时间,才允许从队列中取出

7.2 架构图

在这里插入图片描述

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

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

相关文章

【大数据技术Hadoop+Spark】Spark RDD创建、操作及词频统计、倒排索引实战(超详细 附源码)

需要源码和数据集请点赞关注收藏后评论区留言私信~~~ 一、RDD的创建 Spark可以从Hadoop支持的任何存储源中加载数据去创建RDD,包括本地文件系统和HDFS等文件系统。我们通过Spark中的SparkContext对象调用textFile()方法加载数据创建RDD。 1、从文件系统加载数据创…

基于 Tensorflow 2.x 实现多层卷积神经网络,实践 MNIST 手写数字识别

一、MNIST 数据集 上篇文章中使用了Tensorflow 2.x 搭建了对层的 BP 神经网络,经过训练后发现准确率只有 96.8% 对于单环境的图片识别场景来说,还是有点偏低,本文使用多层的卷积代替BP网络中的隐藏层对模型进行优化。 下面是上篇文章地址&am…

C语言重点解剖第12课笔记

1.int* a,b; a和b的类型不一样, a是指针,b是整型。 typedef int* int_p; int_p a,b; 或者int* a,*b; 这样写的话,a和b都是指针类型。 #define int_p int*;这是纯粹的文本替换。 typedef定义之后是一种独立类型。 2.大部分注释都换成了…

Linux网络协议之HTTP协议(应用层)

Linux网络协议之HTTP协议(应用层) 文章目录Linux网络协议之HTTP协议(应用层)1.HTTP协议的概念2.HTTP协议中URL的理解3.HTTP协议的数据流4.HTTP协议的格式4.1 HTTP请求格式4.2 HTTP响应格式5.HTTP协议格式图解6.HTTP协议版本7.HTTP协议请求方法7.1 GET方法:获取资源7…

OWASP API安全Top 10

文章目录API1-失效的对象级授权API2-失效的用户认证API3-过度的数据暴露API4-缺乏资源和速率控制API5-失效的功能级授权API6-批量分配API7-安全性配置错误API8-注入API9-资产管理不当API10-日志记录和监控不足在API安全发展的过程中,除了各大安全厂商和头部互联网企…

计算机基础学习笔记:操作系统篇之硬件结构,CPU的基本工作原理

一、CPU的是如何运行程序的? 本文知识来源小林Coding阅读整理思考,原文链接请见以下: https://xiaolincoding.com/os/1_hardware/how_cpu_run.html#图灵机的工作方式 问题引入 程序的执行过程?例如 12 的具体过程是怎么样的&…

Windows VS2015 cmake编译Gtest并进行测试

1.下载Gtest 下载网址:https://github.com/google/googletest/releases 也可以直接使用下载好的附件 解压,放到一个目录中,演示所用,直接存放D盘了。 2.使用CMake生成vs编译工程 选好下图中两个路径,点击Configure…

用 AWTK 和 AWPLC 快速开发嵌入式应用程序 (8)- AWBlock

AWPLC 目前还处于开发阶段的早期,写这个系列文章的目的,除了用来验证目前所做的工作外,还希望得到大家的指点和反馈。如果您有任何疑问和建议,请在评论区留言。 1. 背景 AWTK 全称 Toolkit AnyWhere,是 ZLG 开发的开源…

玩以太坊链上项目的必备技能(OOP-接口-Solidity之旅十一)

接口(interface) 我们知道在Java里接口是特殊的抽象类,限制多于抽象类,但随着Java版本的更新,Java中的接口是越来越趋于抽象类了(这样说,可能有点不妥,因为接口本就是特殊的抽象类&…

自己整理的Java面试题(下)

目录五.Java框架部分Spring1.Spring中的拦截器,过滤器组件介绍?2.说一下spring的IOC?3.Spring中的异常处理:4.jdk动态代理和cglib动态代理:5.Spring Bean生命周期:6.Spring IOC原理:7.BeanFacto…

RK3568平台开发系列讲解(Camera篇)Camera API v2框架

🚀返回专栏总目录 文章目录 一、Camera API v2框架二、preview流程三、核心模块沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇讲介绍 Camera API v2框架。 一、Camera API v2框架 应用框架:应用代码位于应用框架级别,它使用 Camera 2 API 与相机硬件进行交互…

【正点原子I.MX6U-MINI】u-boot过程移植详解

正点原子的I.MX6ULL开发板参考的是NXP官方的I.MX6ULL EVK开发板做的硬件。 Linux的移植要复杂的多,在移植Linux之前我们需要先移植一个 bootloader 代码,这个 bootloader 代码用于启动Linux 内核,bootloader有很多,常用的就是 U-…

蓝桥杯C/C++百校真题赛(1期)Day3题解(等差数列、回路计数)

Q1 等差数列 由于保证了题目给出的一定是一个等差数列的部分项,且等差数列具有单调性质,所以根据大小排序后最小的did_idi​就是所求等差数列的公差ddd, 又因为求的是最小,所以n(an−a1)/d1,特别的,当ana1,d0时,特判输…

[数据库]复习杂项

(画师蓝鸟mo13tto) 数据库笔记(补充)——候选码的确定方法 求最小依赖集 最小函数依赖集Fm的定义,求法以及举例 当然这篇文章后半部分有误:【通俗易懂】关系模式范式分解教程 3NF与BCNF口诀!小白也能看…

企业数字化转型:数据集成是成功的关键

按照数据的生命周期,我们通常将大数据技术分为数据集成、数据存储、批/流处理、数据查询与分析、数据调度与编排、数据开发、BI 7 个部分。 数据集成是什么? 可以看到数据集成在数据生命周期的最前面位置,它负责将多个来自不同数据源的数据…

[附源码]计算机毕业设计Python保护濒危动物公益网站(程序+源码+LW文档)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等…

vue3 中的响应式设计原理

Vue 3 中的响应式原理可谓是非常之重要,通过学习 Vue3 的响应式原理,不仅能让我们学习到 Vue.js 的一些设计模式和思想,还能帮助我们提高项目开发效率和代码调试能力。 一、Vue 3 响应式使用 1. Vue 3 中的使用 当我们在学习 Vue 3 的时候&…

51单片机——动态数码管实验,小白讲解,相互学习

多位数码管介绍: 多位数码管,即两个或两个以上单个数码管并列集中在一起形成一体的数码管。当多位一体时,他们内部的公共端是独立的,二负责显示什么数字的段线(a-dp)全部是连接在一起的,独立的公…

中国水文地质图集

概述 水文地质图集部分来源于 《中华人民共和国水文地质图集》(地质出版社1979年版)的GIS数字化版(数据格式:JPEG),图集是由全国性、地区性和分省/自治区/直辖市等三类图幅组成,共68幅图(实际收集到55幅图)。 主要内容包括:水文地质图、地下热水分布图、水化学图、…

数据结构C语言版 —— 栈的实现

文章目录栈1. 基本概念2. 栈的实现1) 初始化栈2) 栈的扩容3) 判断栈是否为空4) 入栈5) 出栈6) 获取栈顶元素7) 获取栈中元素个数8) 销毁栈栈 1. 基本概念 栈(Stack):一种特殊的线性表,其只限定于在表尾进行插入或者删除操作。进行数据插入和删除操作的…