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

【MQ】RabbitMQ 高可用延时功能的探究

延迟消息如果使用延时交换机来实现,如果数据量过大,就会很占 CPU 资源,轻则时间误差大,重则 RabbitMQ 宕机

一、针对一个 RabbitMQ 节点

(1)利用队列+ ttl,将延迟消息根据 delay 的时间进行分级

比如两小时、一天,这两个级别:

  1. 小于两天的消息直接放在延迟交换机
  2. 两天到一天的交给 ttl 为两小时的队列
  3. 其余的交给 ttl 为一天的队列

而两个 ttl 队列绑定同一个死信交换机,死信被咱们的服务处理后重新发送(delay - ttl,或者消息本身携带时间的信息,重新计算 delay),再根据新的 delay 判断前往哪里

这里可行的原因是,队列 + ttl 的 CPU 消耗只用于队列头的那一条消息,在这里就可以保存很多消息

对于这个问题,RabbitMQ 这个插件更适合于 delay 比较均匀的情况,一般到这里就结束了,但是有个坑点,一个热点时间的延迟消息会一起进入延迟交换机

(2)对于热点时间的消息处理

可以在发送到延迟交换机之前,先监控其数量(可以用 Redis 实现一个计数器),控制在一个可控的量级,如 10W,在范围内则发送,否则

  1. 存储起来,可以是 Mysql,也可以是 Redis,或者利用 RabbitMQ 的优先级队列,但是要主动的获取消息而不是监听
  2. 周期性的扫描(五分钟左右),监控 RabbitMQ 延时交换机的健康值,可以加入就加入(delay 小的先加入)(也可以 delay 相同的同一种消息合并成一个,与监听器约定一下这种情况)
  3. 但可能因为没及时扫描,导致新 delay ≤ 0,因此可能产生误差,我们可以将 delay 小于周期间隔的
    1. 接受误差的范围内的不给予处理
    2. 直接本地延时任务、交给 Redis 做延时队列分担多出来的这一份数据量(反正就是天女散花,将这个任务分担给其他服务)

如果是一个热点时间,消息的 delay 都很接近,但其实经过多次周期性的扫描,这个热点时间的消息大部分都可以进入延时交换机,再用 Redis 在最后接近热点时间,“冲刺”的时候助 RabbitMQ 一臂之力

以上是单机情况下我能想到的最好方案了,世界上没有绝对完美的东西,你可能描述一个极端的场景依旧可能出现问题,因此你可以解决其本质原因 “就是一个 MQ 处理不过来”

对于这种大数据量的情况,这一业务独享一个 RabbitMQ,减少 CPU 在其他业务的损耗

二、多个 RabbitMQ 节点相互扶持

因为集群针对的是队列中消息的同步,并不会同步延时交换机暂存的消息,这样不同的 RabbitMQ 去维护各自的延迟交换机就行了,让各个节点的延时交换机的数据量处在安全值范围内,之后到达队列再消息同步

你可能说,那宕机了,岂不是丢失了🤣,我们这样子做就是为了多个节点相互扶持,单机不宕机啊,同步了的话那每个节点都岌岌可危

  1. 旧的延时消息持久化了,有保证可靠性,重启即可
  2. 新的延时消息前往存活的节点

你可以维护一个表,就是延时消息表,设立时间误差进行周期性的扫描,将过期未删除记录的消息重新发送,作为一个兜底**(可以用任务调度平台去控制这些任务吧,如果 MQ 都很健康,其实也没必要一直扫描)**

但这种很极端,因为这样子做的话,我们就相当于不相信 MQ,一棒子打死所有人,但其实消息到 MQ 后,我们就只能全身心相信 MQ 持久化了我们的消息

我们不如直接重启这个挂掉的 MQ

注意:记得给每个节点安装延时交换机的插件

三、ttl 消息 + 优先级队列

RabbitMQ 还可以实现优先级队列

暂时不考虑 CPU 的损耗,我认为在定时方面可以忽略不记
优先级队列还不支持策略定义(但除了一些特殊需要,我们平时也用不到)

因此,如果将消息的 max - ttl 作为优先级,放入优先级队列里,是可以实现队列头为最小的 ttl,最先过期的会排在前面

定义队列的时候,设置 args “x-max-priority” 为 max,max 最大可以取 255,所以其优先级数量只可以为 1-255 个,一些甚至只能是 2-10 个

也就是说 ttl 的可选访问很小(固定只能 1-255 这个整数范围,只能控制时间单位改变其值域)

这个方法实现的延迟功能,取值有限,只能在特殊场景下使用

四、其他

RabbitMQ 的解决方案并不是绝对完美的,如果有特殊要求可以考虑其他的技术栈

相关文章:

【MQ】RabbitMQ 高可用延时功能的探究

延迟消息如果使用延时交换机来实现,如果数据量过大,就会很占 CPU 资源,轻则时间误差大,重则 RabbitMQ 宕机 一、针对一个 RabbitMQ 节点 (1)利用队列 ttl,将延迟消息根据 delay 的时间进行分级…...

Maven入门核心知识点总结

Maven 1. POM(Project Object Model)2. 坐标(Coordinates)3. 依赖管理(Dependency Management)4. 常用五个生命周期(Life Circle)5. Maven 仓库(Maven Repository&#x…...

【力扣】138.随机链表的复制

AC截图 题目 代码 使用哈希存储<旧节点&#xff0c;新结点> /* // Definition for a Node. class Node { public:int val;Node* next;Node* random;Node(int _val) {val _val;next NULL;random NULL;} }; */class Solution { public:Node* copyRandomList(Node* hea…...

编程语言的深度剖析:从语法到性能优化

引言 随着软件开发的不断进化&#xff0c;编程语言的选择对项目的成功与否具有关键影响。今天的开发者面临着丰富多样的编程语言选择&#xff1a;每一种语言都有独特的优势、特性和适用场景。然而&#xff0c;语言的设计理念、运行机制和优化技巧背后的技术细节却常常被忽视。本…...

台湾精锐APEX减速机在半导体制造设备中的应用案例

半导体制造设备对传动系统的精度、可靠性和稳定性要求极高&#xff0c;台湾精锐APEX减速机凭借其低背隙、高精度和高刚性等优势&#xff0c;在半导体制造设备中得到了广泛应用。 案例一&#xff1a;晶圆切割设备 1.应用场景 在晶圆切割过程中&#xff0c;设备需要高精度的运…...

Rocketmq 和 Rabbitmq ,在多消费者的情况下,可以实现顺序消费吗

在多消费者的情况下&#xff0c;RocketMQ 和 RabbitMQ 都可以实现顺序消费&#xff0c;但它们的实现机制和适用场景有所不同。以下是对两者的详细分析和对比&#xff1a; 1. RocketMQ 的顺序消费 1.1 实现机制 顺序消息&#xff1a;RocketMQ 支持顺序消息&#xff08;Orderly …...

Springboot原理(面试高频)

目录 一、 配置优先级 ​编辑 二、Bean管理 ​​​​​​​2.1&#xff1a;获取Bean ​编辑 ​​​​​​​2.2&#xff1a;Bean作用域 ​​​​​​​​​​​​​​2.3&#xff1a;第三方Bean 三、Springboot底层原理 3.1&#xff1a;起步依赖 3.1.1&#xff1a;ma…...

2024 Rust现代实用教程:1.1Rust简介与安装更新

文章目录 一、Rust安装二、更新Rust三、Rust的Stable与Nightly版本四、卸载ubuntu安装的cargo和rustup五、rust源设置六、rust交叉编译工具链说明 rustup稳定版交叉编译步骤 步骤 1&#xff1a;安装目标组件步骤 2&#xff1a;安装交叉编译工具链步骤 3&#xff1a;配置环境变…...

yolov11模型在Android设备上运行【踩坑记录】

0) 参考资料: https://github.com/Tencent/ncnn?tabreadme-ov-file https://github.com/pnnx/pnnx https://github.com/nihui/ncnn-android-yolov5 https://github.com/Tencent/ncnn?tabreadme-ov-file 1) &#xff1a;将xxx.pt模型转化成 xxx.onnx ONNX&#xff08;Ope…...

提示工程:少样本提示(Few-shot Prompting)

少样本提示&#xff08;Few-shot Prompting&#xff09;是一种利用大语言模型从少量示例样本中学习并处理任务的方法。它的核心思想是利用大语言模型的上下文学习能力&#xff0c;通过在提示中增加“示例样本”来启发大语言模型达到举一反三的效果。这种方法避免了重新训练或者…...

方舟字节码原理剖析:架构、特性与实践应用

方舟字节码原理剖析&#xff1a;架构、特性与实践应用 一、引言 在当今软件行业高速发展的大背景下&#xff0c;应用程序的性能、开发效率以及跨平台兼容性成为了开发者们关注的核心要素。编译器作为软件开发流程中的关键工具&#xff0c;其性能和特性直接影响着软件的质量和…...

深入Linux系列之环境变量

深入Linux系列之环境变量 那么在之前的内容中&#xff0c;我们已经介绍了我们Linux进程的一些关键属性&#xff0c;例如进程编号以及进程状态和进程优先级&#xff0c;那么本篇文章接介绍Linux的环境变量这一知识点&#xff0c;那么废话不多说&#xff0c;我们进入环境变量的讲…...

国产编辑器EverEdit - Web预览功能

1 Web预览 1.1 应用场景 在编辑HTML文件时&#xff0c;可以通过EverEdit的Web预览功能&#xff0c;方便用户随时观察和调整HTML代码。 1.2 使用方法 1.2.1 使用EverEdit内部浏览器预览 选择主菜单查看 -> Web预览&#xff0c;或使用快捷键Ctrl B&#xff0c;即可打开Ev…...

C#中的Frm_Welcome.Instance.Show(),是什么意思

Frm_Welcome.Instance.Show() 是一种常见的单例模式&#xff08;Singleton Pattern&#xff09;实现方式&#xff0c;通常用于在应用程序中确保某个窗体&#xff08;Form&#xff09;只有一个实例&#xff0c;并通过该实例显示窗体。以下是对这段代码的详细解释&#xff1a; 代…...

07苍穹外卖之redis缓存商品、购物车(redis案例缓存实现)

课程内容 缓存菜品 缓存套餐 添加购物车 查看购物车 清空购物车 功能实现&#xff1a;缓存商品、购物车 效果图&#xff1a; 1. 缓存菜品 1.1 问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压…...

C++开发(软件开发)常见面试题

目录 1、C里指针和数组的区别 2、C中空指针请使用nullptr不要使用NULL 3、http/https区别和头部结构&#xff1f; 4、有了mac地址为什么还要ip地址&#xff1f;ip地址的作用 5、有了路由器为什么还要交换机&#xff1f; 6、面向对象三大特性 7、友元函数 8、大端小端 …...

人工智能-A*算法与卷积神经网络(CNN)结合实现路径规划

以下是一个将 A* 算法与卷积神经网络(CNN)结合实现路径规划的代码示例。主要思路是使用 A* 算法生成训练数据,然后用这些数据训练一个 CNN 模型,让 CNN 学习如何预测路径,最后使用训练好的 CNN 模型进行路径规划。 代码实现 import numpy as np import heapq import tor…...

蓝桥杯备赛——进制转化相关问题

目录 一、基础概念 二、问题研究&#xff08;1&#xff09; 代码解读&#xff1a; 1. transfer 函数 代码功能概述 详细步骤 2. main 函数 代码功能概述 详细步骤 三、运用递归解决 &#xff08;一&#xff09; 代码如下&#xff1a; 代码解读&#xff1a; &#…...

DevOps的个人学习

一、DevOps介绍 软件开发最初是由两个团队组成&#xff1a; 开发团队&#xff1a;负责设计和构建系统。运维团队&#xff1a;负责测试代码后部署上线&#xff0c;确保系统稳定安全运行。 这两个看似目标不同的团队需要协同完成一个软件的开发。DevOps整合了开发与运维团队&a…...

使用Pytorch训练一个图像分类器

一、准备数据集 一般来说&#xff0c;当你不得不与图像、文本或者视频资料打交道时&#xff0c;会选择使用python的标准库将原始数据加载转化成numpy数组&#xff0c;甚至可以继续转换成torch.*Tensor。 对图片而言&#xff0c;可以使用Pillow库和OpenCV库对视频而言&#xf…...

《ARM64体系结构编程与实践》学习笔记(四)

MMU内存管理 1.MMU内存管理&#xff08;armv8.6手册的D5章节&#xff09;&#xff0c;MMU包含快表TLB&#xff0c;TLB是对页表的部分缓存&#xff0c;页表是存放在内存里面的。 AArch64仅仅支持Long Descriptor的页表格式&#xff0c;AArch32支持两种页表格式Armv7-A Short De…...

01-SDRAM控制器的设计——案例总概述

本教程重点▷▷▷ 存储器简介。 介绍 SDRAM 的工作原理。 详细讲解SDRAM 控制的Verilog 实现方法。 PLL IP和FIFO IP 的调用&#xff0c;计数器设计&#xff0c;按键边沿捕获&#xff0c;数码管控制。 完成SDRAM控制器应用的完整案例。 Signal Tap 调试方法。 准备工作▷…...

京准:NTP卫星时钟服务器对于DeepSeek安全的重要性

京准&#xff1a;NTP卫星时钟服务器对于DeepSeek安全的重要性 京准&#xff1a;NTP卫星时钟服务器对于DeepSeek安全的重要性 在网络安全领域&#xff0c;分布式拒绝服务&#xff08;DDoS&#xff09;攻击一直是企业和网络服务商面临的重大威胁之一。随着攻击技术的不断演化…...

uniapp访问django目录中的图片和视频,2025[最新]中间件访问方式

新建中间件, middleware.py 匹配,以/cover_image/ 开头的图片 匹配以/episode_video/ 开头的视频 imageSrc: http://192.168.110.148:8000/cover_image/12345/1738760890657_mmexport1738154397386.jpg, videoSrc: http://192.168.110.148:8000/episode_video/12345/compres…...

RuoYi-Vue-Oracle的oracle driver驱动配置问题ojdbc8-12.2.0.1.jar的解决

RuoYi-Vue-Oracle的oracle driver驱动配置问题ojdbc8-12.2.0.1.jar的解决 1、报错情况 下载&#xff1a;https://gitcode.com/yangzongzhuan/RuoYi-Vue-Oracle 用idea打开&#xff0c;启动&#xff1a; 日志有报错&#xff1a; 点右侧m图标&#xff0c;maven有以下报误 &…...

python脚本实现windows电脑内存监控内存清理(类似rammap清空工作集功能)

import ctypes import psutil import time import sys import os from datetime import datetime import pyautogui# 检查管理员权限 def is_admin():try:return ctypes.windll.shell32.IsUserAnAdmin()except:return False# 内存清理核心功能 def cleanup_memory(aggressivene…...

【狂热算法篇】并查集:探秘图论中的 “连通神器”,解锁动态连通性的神秘力量

嘿&#xff0c;朋友们&#xff01;喜欢这个并查集的讲解吗 记得点个关注哦&#xff0c;让我们一起探索算法的奥秘&#xff0c;别忘了一键三连&#xff0c;你的支持是我最大的动力&#xff01; 欢迎拜访&#xff1a;羑悻的小杀马特.-CSDN博客 本篇主题&#xff1a;深度剖析并查…...

SpringBoot中实现动态数据源切换

SpringBoot中实现动态数据源切换 文章目录 SpringBoot中实现动态数据源切换SpringBoot中实现动态数据源切换基础知识1. 什么是数据源&#xff1f;2. 动态数据源切换的概念3. Spring Boot 中的默认数据源配置4. 动态数据源的挑战5. Spring 中的数据源切换方式 设计思路1. 明确应…...

数据结构及排序算法

数据结构 线性结构 ◆线性结构:每个元素最多只有一个出度和一个入度,表现为一条线状。线性表按存储方式分为顺序表和链表。 存储结构: ◆顺序存储:用一组地址连续的存储单元依次存储线性表中的数据元素,使得逻辑上相邻的元素物理上也相邻。 ◆链式存储:存储各数据元素的结点…...

Python基础-元组tuple的学习

在 Python 中&#xff0c;元组&#xff08;tuple&#xff09;是一种不可变的序列类型&#xff0c;允许存储不同类型的元素。元组非常类似于列表&#xff08;list&#xff09;&#xff0c;但与列表不同的是&#xff0c;元组一旦创建&#xff0c;就不能修改其内容。 1 元组的创建…...