消息中间件RabbitMQ

news2025/1/23 6:08:17

文章目录

    • 1. 协议
    • 2. RabbitMQ架构原理
    • 3.内存管理
    • 4.磁盘控制
    • 5. RabbiMQ 插件管理
    • 6. 死信
      • 6.1 死信队列
      • 6.2 延时插件
    • 7. 高可用集群方案
      • 7.1 普通集群模式
      • 7.2 镜像集群模式
      • 7.3 基于HAproxy+Keepalived搭建高可用
    • 8.可靠性投递
      • 8.1 消息从生产者发送到Broker
        • 两种确认机制
      • 8.2 消息从Exchange路由到Queue
      • 8.3 消息在Queue中存储
      • 8.4 消费者订阅Queue并消费消息
      • 8.5 其它保障消息可靠性的方案
        • 8.5.1 消费者回调
        • 8.5.2 消息补偿
        • 8.5.3 消息幂等性
        • 8.5.4 消息的顺序性
    • 9.实践经验分享
      • 9.1 信息落库 + 定时任务
      • 9.2 减少连接数

1. 协议

协议类型事务持久化代表MQ其它描述
AMQ支持支持RabbitMQ, ActiveMQ金融行业,在可靠性消息处理上有优势
MQTT不支持不支持RabbitMQ, ActiveMQ计算能力有限、低带宽、网络不稳定的场景
OpenMessagingRocketMQ流处理领域
Kafka协议不支持支持Kafka消息内部通过长度来分隔,由一些基本数据类型组成

2. RabbitMQ架构原理

在这里插入图片描述

  • 交换机类型
    ① 直连Direct,使用明确的绑定键,适用于业务目的明确的场景
    在这里插入图片描述
    ② 主题TOPIC
    使用支持通配符的的绑定键。适用于根据业务主题过滤消息的场景。
    #代表匹配0个或者多个单词;*代表匹配不多不少一个单词;每个单词用点号隔开
    在这里插入图片描述
    ③ 广播Fanout
    无需绑定键。适用于通用类业务消息。
    在这里插入图片描述

3.内存管理

内存调整的两种模式,相对模式和绝对模式

  • 相对模式
rabbitmqctl set_vm_memory_high_ watermark <fraction>

fraction为内存阈值,默认是0.4, 表示RabbitMQ使用的内存超过系统内存的40%时,会产生内存告警

  • 绝对模式
rabbitmqctl set_vm_memory_high_watermark absolute <value>

absolute:绝对值,固定大小,单位为KB、MB、GB

  • 内存换页
vm_memory_high_watermark_paging_ ratio=0.5

在RabbitMQ达到内存阈值并阻塞生产者之前,会尝试将内存中的消息换页到磁盘,以释放内存空间。当换页阈值大于1时,相当于禁用了换页功能

4.磁盘控制

rabbitmqctl set_disk_free_limit <limit>
rabbitmqctl set_disk_free_limit mem_relative <fraction>
# limit 为绝对值,KB、MB、GB
# fraction 为相对值,建议 1.0~2.0 之间
# rabbitmq.conf
disk_free_limit.relative=1.5
# disk_free_limit.absolute=50MB

RabbitMQ 通过磁盘阈值参数控制磁盘的使用量,当磁盘剩余空间小于磁盘阈值时,RabbitMQ 同样会阻塞生产者,避免磁盘空间耗尽。

磁盘阈值默认 50M,由于是定时检测磁盘空间,不能完全消除因磁盘耗尽而导致崩溃的可能性,比如在两次检测之间,磁盘空间从大于 50M 变为 0M。

一种相对谨慎的做法是将磁盘阈值大小设置与内存相等

5. RabbiMQ 插件管理

插件列表: rabbitmq-plugins list
启用插件:rabbitmq-plugins enable xxxx
卸载插件:rabbitmq-plugins disable xxxx

6. 死信

适用于
① 订单过期关闭;
② 消息被消费者拒绝并且未设置重回队列:(NACK || Reject ) && requeue == false;
③ 队列达到最大长度,超过了 Max length(消息数)或者 Max length bytes(字节数)
在这里插入图片描述

6.1 死信队列

队列的消息过期属性:x-message-ttl
RabbitMQ 的消息也有单独的过期时间属性
如果同时指定了 Message TTL 和 Queue TTL,则小的那个时间生效。

消息过期以后,如果没有任何配置,直接丢弃,可以通过配置让这样的消息变成死信(Dead Letter)

  • 创建一个死信交换机 DLX(Dead Letter Exchange)
  • 创建一个死信队列 DLQ(Dead Letter Queue,绑定死信交换机,通过"#"绑定,代表无条件路由
  • DLX 实际上也是普通的交换机,DLQ 也是普通的队列
    在这里插入图片描述
    队列指定了 DLX,就会发送到 DLX。如果 DLX 绑定了 DLQ,就会路由到 DLQ。

流转原理
在这里插入图片描述
使用死信队列实现延时消息的缺点:
① 如果统一用队列来设置消息的 TTL,当梯度非常多的情况下,比如 1 分钟,2分钟,5 分钟,10 分钟,20 分钟,30 分钟……需要创建很多交换机和队列来路由消息
② 如果单独设置消息的 TTL,则可能会造成队列中的消息阻塞——前一条消息没有出队(没有被消费),后面的消息无法投递(比如第一条消息过期 TTL 是 30min,第二条消息 TTL 是 10min。10 分钟后,即使第二条消息应该投递了,但是由于第一条消息还未出队,所以无法投递)。

6.2 延时插件

① cd /usr/lib/rabbitmq/lib/rabbitmq_server-3.8.11/plugins
② wget
https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases/download/3.8.9/
rabbitmq_delayed_message_exchange-3.8.9-0199d11c.ez
③启用 rabbitmq_delayed_message_exchange
rabbitmq-plugins enable rabbitmq_delayed_message_exchange
④重启 rabbitmq
service rabbitmq-server restart 或者 rabbitmq-server restart
⑤ 声 明 一 个 x-delayed-message 类 型 的 Exchange 来 使 用
delayed-messaging 特 性 。 x-delayed-message 是 插 件 提 供 的 类 型 , 并 不 是
RabbitMQ 本身的(区别于 direct、topic、fanout、headers)
在这里插入图片描述
本质:定时器取出过期消息,违背了队列先进先出的原则,经延时插件路由到延时队列。要求消息实现持久化

7. 高可用集群方案

RabbitMQ集群里,至少有一个磁盘节点,它用来持久保存我们的元数据,如果RabbitMQ是单节点运行,则默认就是磁盘节点。但是为了提高性能,其实不需要所有节点都是disc的节点,根据需求分配即可。

#加入集群时设置节点类型
rabbitmqctlchange_cluster_node_type disc|ram

磁盘节点
将元数据(包括队列名字属性、交换机的类型名字属性、绑定、vhost) 放在磁盘中。未指定类型的情况下,默认为磁盘节点。

内存节点
就是将元数据都放在内存里,内存节点的话,只要服务重启,该节点的所有数据将会丢失。

7.1 普通集群模式

在这里插入图片描述
一个节点作为Master,存储元数据,其它节点作为Slave,从Master复制元数据

7.2 镜像集群模式

  • 一个节点作为Master,存储元数据和数据,其它节点作为Slave,从Master复制元数据和数据。
  • 需要一个负载均衡的组件(例如HAProxy,LVS,Nignx),由负载的组件来做路由。这个时候,只需要连接到负载组件的IP地址就可以
    在这里插入图片描述
    由普通集群模式 转变为 镜像集群模式的操作:
    在这里插入图片描述

7.3 基于HAproxy+Keepalived搭建高可用

如果负载的组件也挂了,客户端就无法连接到任意一台MQ的服务器。所以负载软件本身也需要做一个集群(双机热备)。
双机热备
两个Keepalived抢占一个VIP192.168.8.149。谁抢占到这个VIP,应用就连接到谁,来执行对MQ的负载
在这里插入图片描述
Keepalived挂了一个节点,没有影响,因为BACKUP会变成MASTER,抢占VIP。HAProxy挂了一个节点,没有影响,VIP会自动路由的可用的HAProxy服务,RabbitMQ挂了一个节点,没有影响,HAProxy会自动负载到可用的节点

8.可靠性投递

在这里插入图片描述

8.1 消息从生产者发送到Broker

Broker不给应答,生产者不断地发送。

两种确认机制

第一种Transaction(事务)模式,第二种Confirm(确认)模式
① Transaction(事务)模式
在这里插入图片描述
② Confirm(确认)模式

  • 普通确认模式
    在这里插入图片描述
    这种发送1条确认1条的方式,发送消息的效率不太高
  • 批量确认

批量的数量的确定。对于不同的业务,到底发送多少条消息确认一次?数量太少,效率提升不上去。数量多的话,比如我们发1000 条消息才确认一次,如果前面999条消息都被服务端接收了,如果第1000条消息被拒绝了,那么前面所有的消息都重发。

  • 异步确认模式
    异步确认模式需要添加一个ConfirmListener,并且用一个SortedSet来维护一个批次中没有被确认的消息。

8.2 消息从Exchange路由到Queue

消息无法路由到正确队列

两种解决办法:
一是让服务端重发给生产者,
二是让交换机路由到另一个备份的交换机

8.3 消息在Queue中存储

RabbitMQ的服务或者硬件发生故障,比如系统宕机、重启、关闭等等,可能会导致内存中的消息丢失

四种解决方案:队列持久化,交换机持久化,
消息持久化,集群部署

8.4 消费者订阅Queue并消费消息

如果消费者收到消息后没来得及处理即发生异常,或者处理过程中发生异常,会导致④失败。服务端应该以某种方式得知消费者对消息的接收情况,并决定是否重新投递这条消息给其他消费者。

没有收到ACK的消息,消费者断开连接后,RabbitMQ会把这条消息发送给其他消费者。
如果没有其他消费者,消费者重启后会重新消费这条消息

消费者给Broker默认自动ACK应答,消费者会在收到消息的时候就自动发送ACK,而不是在方法执行完毕的时候发送ACK

若等消息消费完毕或者方法执行完毕才发送ACK,需要先把自动ACK设置成手动ACK。即把autoAck设置成false
这个时候RabbitMQ会等待消费者显式地回复ACK后才从队列中移去消息

8.5 其它保障消息可靠性的方案

生产者最终确定消费者有没有消费成功的方式

8.5.1 消费者回调

调用生产者AP;发送响应消息给生产者

8.5.2 消息补偿

约定超时时间;定时任务重发;梯度式重发;重发消息要控制次数;

8.5.3 消息幂等性

用户对于同一操作发起的一次或者多次请求,最后的结果都
是相同的,这就是幂等性

避免消息的重复消费:
每一条消息生成一个唯一的业务 ID,通过日志或者消息落库来做重复控制。
业务要素一致(付款人 ID、商户 ID、交易类型、金额、交易地 点、交易时间)可能是同一笔消息

8.5.4 消息的顺序性

消息的顺序性指的是消费者消费消息的顺序跟生产者生产消息的顺序是一致的。

一个队列有多个消费者时,一个队列仅有一个消费者的情况才能保证顺序消费(不同的业务消息发送到不同的专用的队列)

9.实践经验分享

9.1 信息落库 + 定时任务

将需要发送的消息保存在数据库中,可以实现消息的可追溯和重复控制,需要配合定时任务来实现…
① 将需要发送的消息登记在消息表中
② 定时任务一分钟或半分钟扫描一次,将未发送的消息发送到 MQ 服务器,并且修改状态为已发送

9.2 减少连接数

在发送大批量消息的情况下,创建和释放连接依然有不小的开销。我们可以跟接收方约定批量消息的格式,比如支持 JSON 数组的格式,通过合并消息内容,可以减少生产者/消费者与Broker 的连接。

建议单条消息不要超过 4M(4096KB),一次发送的消息数需要合理地控制

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

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

相关文章

数据Kylin(三):Kylin配置

Kylin配置 一、kylin.metadata.url 指定元数据库路径,默认值为 kylin_metadata@hbase 二、kylin.metadata.sync-retries 指定元数据同步重试次数,默认值为 3 三、kylin.env.hdfs-working-dir 指定 Kylin 服务所用的 HDFS 路径,默认值为 /kylin,请确保启动 Kylin 实例的用户…

【面试题】对闭包的理解?什么是闭包?

大厂面试题分享 面试题库后端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★地址&#xff1a;前端面试题库闭包的背景由于js中只有两种作用域&#xff0c;全局作用域和函数作用域&#xff0c;而在开发场景下&#xff0c;将变量暴露在全局作用域下的时候…

云盘满了怎么办?阿里云服务器云盘扩容操作了解一下

1.背景 2.确定扩容云盘类型与控制台操作 3.ECS实例内部扩容操作说明 3.1 ECS实例内部执行扩容分区 3.2 ECS实例内部执行扩容文件系统 1.背景软件应用的数据库所在服务器磁盘使用率已经达到97%,服务器操作实例如下: 一旦使用达到上限,所有的数…

python基于django的 大学生健康管理系统

随着时代的发展,大学生的数量与日预增但是相对的也出现了很多心理问题,大学生因为各类心理引发的社会问题已经受到了很多人的关注,所以如何更好的培养大学生正确的心理健康问题是现在很多大学多面临的一个重要的问题。 系统设置了三种身份的登录,包括管理员,医生和学生。其中管…

SpringBoot 实现 Excel 导入导出,百万数据量,性能爆表!

最近我做过一个MySQL百万级别数据的excel导出功能&#xff0c;已经正常上线使用了。这个功能挺有意思的&#xff0c;里面需要注意的细节还真不少&#xff0c;现在拿出来跟大家分享一下&#xff0c;希望对你会有所帮助。原始需求&#xff1a;用户在UI界面上点击全部导出按钮&…

最近面试了一位5年的测试,一问三不知,还反怼我...

最近看了很多简历&#xff0c;很多候选人年限不小&#xff0c;但是做的都是一些非常传统的项目&#xff0c;想着也不能通过简历就直接否定一个人&#xff0c;何况现在大环境越来 越难&#xff0c;大家找工作也不容易&#xff0c;于是就打算见一见。 在沟通中发现&#xff0c;由…

ISYSTEM调试实践8-winIDEA Analyzer功能1

前面几篇介绍了ISYSTEM的基本调试界面和功能&#xff0c;相比我之前用过的IDE&#xff0c;除了几种断点方式和脚本功能以外&#xff0c;应该都是比较简单&#xff0c;稍微操作一下就可以直接上手&#xff0c;后续我将介绍winIDEA的Analyzer 功能。 1 Analyzer简介 iSYSTEM An…

一文带你为PySide6编译MySQL插件驱动

1.概述 最近使用PySide6开发程序&#xff0c;涉及与MySQL的数据交互。但是qt官方自pyqt5.12&#xff08;记不太清了&#xff09;以后不再提供MySQL的插件驱动&#xff0c;只能自己根据qt的源码编译。不过网上大部分都是qt5的MySQL驱动的编译教程。后来搜到了一个qt6的编译教程…

为什么我需要一个网站?必须拥有网站的 5 个理由

当社交媒体似乎统治了互联网时&#xff0c;您可能会问自己&#xff1a;“我需要一个网站吗&#xff1f;” 答案是肯定的&#xff0c;我在这里告诉你为什么。2019 年&#xff0c;70-80% 的人在访问/购买之前会在线研究公司&#xff0c;同样比例的客户可能会流向没有网站的小企业…

vlookup怎么用详细步骤,看这一篇就够了

1、vlookup函数&#xff1a;使用方法 以下便是vlookup函数&#xff0c;功能、语法和参数用法&#xff1a; excel函数vlookup 2、vlookup函数&#xff1a;查询参数 首先&#xff0c;选中F2单元格&#xff0c;然后在编辑栏输入函数公式&#xff1a;VLOOKUP(E2&#xff0c;B&…

JVM - 认识JVM规范

目录 重识JVM JVM规范作用及其核心 JVM 整体组成 理解ClassFile结构 ASM开发 重识JVM JVM概述JVM&#xff1a; Java Virtual Machine&#xff0c;也就是Java虚拟机所谓虚拟机是指&#xff1a; 通过软件模拟的具有完整硬件系统功能的、运行在一个完全隔离环境中的计算机系统…

InstructGPT

文章目录Abstract 给定人类的命令&#xff0c;并且用人工标注想要的结果&#xff0c;构成数据集&#xff0c;使用监督学习来微调GPT-3。 然后&#xff0c;我们对模型输出进行排名&#xff0c;构成新的数据集&#xff0c;我们利用强化学习来进一步微调这个监督模型。 我们把产…

day35|01背包问题、416. 分割等和子集

01背包问题 有n件物品和一个最多能背重量为w的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品只能用一次&#xff0c;求解将哪些物品装入背包里物品价值总和最大。 例&#xff1a;背包最大重量为4。 物品为&#xff1a; 重量价值物品0115物品…

3种方法设置PDF“打开密码”,总有一种适合你

PDF文件是我们工作中经常用到的文件之一&#xff0c;对于重要的文件&#xff0c;设置“打开密码”是一种很好的保护方式。下面就来说说&#xff0c;设置PDF“打开密码”有哪三种方法&#xff1f; 方法一&#xff1a;在线网站加密 市面上有很多可以直接在线上加密PDF文件的产品…

Cortex-M0编程入门

目录1.嵌入式系统编程入门微控制器是如何启动的嵌入式程序设计2.输入和输出3.开发流程4.C编程和汇编编程5.什么是程序映像6.C编程&#xff1a;数据类型7.用C语言操作外设8.Cortex微控制器软件接口标准&#xff08;CMSIS&#xff09;简介标准化内容组织结构使用方法优势1.嵌入式…

综合项目 旅游网 【4.旅游线路名称查询-参数传递】

目录 查询参数的传递 route_list.html4.0代码 header.html2.0代码 修改后台代码 RouteServlet之前 RouteDaoImpl1.0 改进后的RouteDaoImpl2.0 改进后的RouteServlet2.0 ​编辑修改前台代码 route_list.html RouteServlet3.0 旅游线路的详情展示 分析 整体过程 代码实现…

【遇见青山】项目难点:缓存穿透的解决方案

【遇见青山】项目难点&#xff1a;缓存穿透的解决方案1.缓存穿透现象缓存空对象布隆过滤其他方案2.解决方案&#xff0c;缓存空数据1.缓存穿透现象 缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在&#xff0c;这样缓存永远不会生效&#xff0c;这些请求都会打到数据…

常见的内存操作函数

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前是C语言学习者 ✈️专栏&#xff1a;C语言航路 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&a…

Java的异常处理

异常 异常就是程序非正常运行时的报错&#xff0c;不正常就是异常。 异常分类 通常分为两类&#xff1a; Error&#xff1a;错误。通常是Java虚拟机无法解决的严重问题。如&#xff1a;JVM系统内部错误、资源耗尽等严重情况。比如&#xff1a;StackOverflowError和OOM-->…

canvas根据坐标点位画图形-canvas拖拽编辑单个图形形状

首先在选中图形的时候需要用鼠标右击来弹出选择框&#xff0c;实现第一个编辑节点功能 在components文件夹下新建右键菜单 RightMenu文件&#xff1a; <template><div v-show"show" class"right-menu" :style"top:this.ypx;left:this.xpx…