RabbitMQ的应用问题
一、幂等性保障
幂等性是数学和计算机科学中某些运算的性质, 它们可以被多次应⽤, ⽽不会改变初始应⽤的结果
数学上的幂等性:
f(x)=f(f(x)) |x|
数据库操作幂等性:
数据库的 select 操作. 不同时间两次查询的结果可能不同, 但是这个操作是符合幂等性的. 幂等性指的是对资源的影响, ⽽不是返回结果. 查询操作对数据资源本⾝不会产⽣影响, 之所以结果不同, 可能是因为两次查询之间有其他操作对资源进⾏了修改.
应用上的幂等性:
在应⽤程序中, 幂等性就是指对⼀个系统进⾏重复调⽤(相同参数), 不论请求多少次, 这些请求对系统的影响都是相同的效果
非幂等性:⽐如 i++ 这个操作, 就是⾮幂等性的. 如果调⽤⽅没有控制好逻辑, ⼀次流程重复调⽤好⼏次, 结果就会不同.
MQ的幂等性:
对于MQ⽽⾔, 幂等性是指同⼀条消息, 多次消费, 对系统的影响是相同的.⼀般消息中间件的消息传输保障分为三个层级.
1. At most once:最多⼀次. 消息可能会丢失,但绝不会重复传输.
2. At least once:最少⼀次. 消息绝不会丢失,但可能会重复传输.
3. Exactly once:恰好⼀次. 每条消息肯定会被传输⼀次且仅传输⼀次.
RabbitMQ⽀持"最多⼀次"和"最少⼀次".
对于"恰好⼀次", ⽬前RabbitMQ还做不到, 不仅是RabbitMQ, ⽬前市⾯上主流的消息中间件, 都做不到这⼀点.
对于可靠性要求⽐较⾼的场景, 建议使⽤"最少⼀次", 以防⽌消息丢失. "最多⼀次" 会因为消息发送过程中, ⽹络问题, 消费出现异常等种种原因, 导致消息丢失.
以下场景可能会导致消息发送重复(包含但不限于)
①发送时消息重复: 当⼀条消息已被成功发送到服务端并完成持久化, 此时出现了⽹络闪断或者客⼾端宕机, 导致服务端对客⼾端应答失败. 如果此时Producer意识到消息发送失败并尝试再次发送消息, Consumer后续会收到两条内容相同并且Message ID也相同的消息.
② 投递时消息重复: 消息消费的场景下, 消息已投递到Consumer并完成业务处理, 当客⼾端给服务端反馈应答的时候⽹络闪断. 为了保证消息⾄少被消费⼀次, 云消息队列 RabbitMQ 版的服务端在将⽹络恢复后再次尝试投递之前已被处理过的消息, Consumer后续会收到两条内容相同并且Message ID也相同的消息.

但是"最少⼀次", 就会造成⼀个问题, 消费端会收到重复的消息, 也会造成对同⼀条消息进⾏多次处理. ⼀些不重要的业务还好⼀点, 对于重要的业务, 如果不对重复的消息进⾏处理, 会造成严重事故
MQ消费者的幂等性的解决⽅法, ⼀般有以下⼏种:
全局唯⼀ID
1. 为每条消息分配⼀个唯⼀标识符, ⽐如UUID或者MQ消息中的唯⼀ID,但是⼀定要保证唯⼀性.
2. 消费者收到消息后, 先⽤该id判断该消息是否已经消费过, 如果已经消费过, 则放弃处理.
3. 如果未消费过, 消费者开始消费消息, 业务处理成功后, 把唯⼀ID保存起来(数据库或Redis等)
可以使⽤Redis 的原⼦性操作setnx来保证幂等性, 将唯⼀ID作为key放到redis中 (SETNX
messageID 1) . 返回1, 说明之前没有消费过, 正常消费. 返回0, 说明这条消息之前已消费过, 抛
弃.
业务逻辑判断
在业务逻辑层⾯实现消息处理的幂等性.
例如: 通过检查数据库中是否已存在相关数据记录, 或者使⽤乐观锁机制来避免更新已被其他事务更改的数据, 再或者在处理消息之前, 先检查相关业务的状态, 确保消息对应的操作尚未执⾏, 然后才进⾏处理, 具体根据业务场景来处理
二、顺序性保障
消息的顺序性是指消费者消费的消息和⽣产者发送消息的顺序是⼀致的.(⽐如⽣产者发送的消息分别是msg1, msg2, msg3, 那么消费者也是按照msg1, msg2, msg3的顺序进⾏消费的.)
很多业务场景下, 消息的消费是不⽤保证顺序的, ⽐如使⽤MQ实现订单超时的处理. 但有些业务场景, 可能存在多个消息顺序处理的情况. ⽐如⽤⼾信息修改, 对同⼀个⽤⼾的同⼀个资料进⾏修改, 需要保证消息的顺序.

⼀些资料显⽰RabbitMQ的消息能够保障顺序性, 这是不严谨的. 在不考虑消息丢失, ⽹络故障等异常的情况下, 如果只有⼀个消费者, 最好也只有⼀个⽣产者的情况下, 是可以保证消息的顺序性. 如果有多个⽣产者同时发送消息, ⽆法确定消息到达RabbitMQ Broker的前后顺序, 也就⽆法验证消息的顺序性.哪些情况可能会打破RabbitMQ的顺序性呢? 下⾯介绍⼏种常⻅的场景:
1. 多个消费者: 当队列配置了多个消费者时, 消息可能会被不同的消费者并⾏处理, 从⽽导致消息处理的顺序性⽆法保证.
2. ⽹络波动或异常: 在消息传递过程中, 如果出现⽹络波动或异常, 可能会导致消息确认(ACK) 丢失, 从⽽使得消息被重新⼊队和重新消费, 造成顺序性问题.
3. 消息重试:如果消费者在处理消息后未能及时发送确认, 或者确认消息在传输过程中丢失, 那么MQ可能会认为消息未被成功消费⽽进⾏重试, 这也可能导致消息处理的顺序性问题.
4. 消息路由问题: 在复杂的路由场景中, 消息可能会根据路由键被发送到不同的队列, 从⽽⽆法保证全局的顺序性.
5. 死信队列: 消息因为某些原因(如消费端拒绝消息)被放⼊死信队列, 死信队列被消费时, ⽆法保证消息的顺序和⽣产者发送消息的顺序⼀致
顺序保障方案:
消息顺序性保障分为: 局部顺序性保证和全局顺序性保证.

局部顺序性通常指的是在单个队列内部保证消息的顺序. 全局顺序性是指在多个队列或多个消费者之间保证消息的顺序.
注:①在实际应⽤中, 全局顺序性很难实现, 可以考虑使⽤业务逻辑来保证顺序性, ⽐如在消息中嵌⼊序列号,并在消费端进⾏排序处理. 相对⽽⾔, 局部顺序性更常⻅, 也更容易实现.
②RabbitMQ作为⼀个分布式消息队列, 主要优化的是吞吐量和可⽤性, ⽽不是严格的顺序性保证.如 果业务场景确实需要严格的消息顺序, 可能需要在应⽤层⾯进⾏额外的设计和实现
顺序性保证的常⻅策略
1. 单队列单消费者
最简单的⽅法是使⽤单个队列, 并由单个消费者进⾏处理. 同⼀个队列中的消息是先进先出的, 这是
RabbitMQ来帮助我们保证的.
2. 分区消费
单个消费者的吞吐太低了, 当需要多个消费者以提⾼处理速度时, 可以使⽤分区消费. 把⼀个队列分割成多个分区, 每个分区由⼀个消费者处理, 以此来保持每个分区内消息的顺序性(⽐如⽤⼾修改资料后, 发送⼀条⽤⼾资料消息. 消费者在处理时, 需要保证消息发送的先后顺序,但这种场合并不需要保证全局顺序. 只需要保证同⼀个⽤⼾的消息顺序消费就可以. 这时候就可以采⽤把消费按照⼀定的规则, 分为多个区, 每个分区由⼀个消费者处理
RabbitMQ本⾝并不⽀持分区消费, 需要业务逻辑去实现, 或者借助spring-cloud-stream来实现) 3. 消息确认机制
使⽤⼿动消息确认机制, 消费者在处理完⼀条消息后, 显式地发送确认, 这样RabbitMQ才会移除并继续发送下⼀条消息.
4. 业务逻辑控制
在某些情况下, 即使消息乱序到达, 也可以在业务逻辑层⾯实现顺序控制. ⽐如通过在消息中嵌⼊序列号, 并在消费时根据这些信息来处理
三、消息挤压问题
原因分析
消息积压是指在消息队列(如RabbitMQ)中, 待处理的消息数量超过了消费者处理能⼒, 导致消息在队列中不断堆积的现象.
通常有以下⼏种原因:
1. 消息⽣产过快: 在⾼流量或者⾼负载的情况下, ⽣产者以极⾼的速率发送消息, 超过了消费者的处理能⼒.
2. 消费者处理能⼒不⾜: 消费者处理处理消息的速度跟不上消息⽣产的速度, 也会导致消息在队列中积压.
可能原因有:
1) 消费端业务逻辑复杂, 耗时⻓
2) 消费端代码性能低
3) 系统资源限制, 如CPU、内存、磁盘I/O等也会限制消费者处理消息的效率.
4) 异常处理处理不当. 消费者在处理消息时出现异常, 导致消息⽆法被正确处理和确认.
3. ⽹络问题: 因为⽹络延迟或不稳定, 消费者⽆法及时接收或确认消息, 最终导致消息积压
4. RabbitMQ 服务器配置偏低
消息积压可能会导致系统性能下降, 影响⽤⼾体验, 甚⾄导致系统崩溃. 因此, 及时发现消息积压并解决对于维护系统稳定性⾄关重要.
解决⽅案
遇到消息积压时, ⾸先要分析消息积压造成的原因. 根据原因来调整策略.
主要从以下⼏个⽅⾯来解决:
1. 提⾼消费者效率
a. 增加消费者实例数量, ⽐如新增机器
b. 优化业务逻辑, ⽐如使⽤多线程来处理业务
c. 设置prefetchCount, 当⼀个消费者阻塞时, 消息转发到其他未阻塞的消费者.
d. 消息发⽣异常时, 设置合适的重试策略, 或者转⼊到死信队列
2. 限制⽣产者速率. ⽐如流量控制, 限流算法等.
a. 流量控制: 在消息⽣产者中实现流量控制逻辑, 根据消费者处理能⼒动态调整发送速率
b. 限流: 使⽤限流⼯具, 为消息发送速率设置⼀个上限
c. 设置过期时间. 如果消息过期未消费, 可以配置死信队列, 以避免消息丢失, 并减少对主队列的压
⼒
3. 资源与配置优化. ⽐如升级RabbitMQ服务器的硬件, 调整RabbitMQ的配置参数等
相关文章:
RabbitMQ的应用问题
一、幂等性保障 幂等性是数学和计算机科学中某些运算的性质, 它们可以被多次应⽤, ⽽不会改变初始应⽤的结果 数学上的幂等性: f(x)f(f(x)) |x| 数据库操作幂等性: 数据库的 select 操作. 不同时间两次查询的结果可能不同, 但是这个操作是符合幂等性…...
C++14:通过make_index_sequence实现将tuple转换为array
如何将vector转换为array呢 #include <iostream> #include <tuple> #include <array> using namespace std;template <typename V, typename... Types, size_t... I> constexpr auto do_tuple_to_array(tuple<V, Types...>&& tuple, in…...
Linux中修改MySQL密码
Linux中MySQL的密码操作 1、给用户设置/更新密码 mysqladmin -u用户名 -p原密码 password "新密码"该命令在终端直接执行,不需要进入mysql视图 该命令适用于以下情况: 用户的密码为空,为用户设置密码用户密码需要更新,…...
华为OD真题机试-英文输入法(Java)
华为OD机试真题中的“英文输入法”题目主要考察的是字符串处理、单词提取、以及基于前缀的单词联想功能。以下是对该题目的详细解析: 题目描述 主管期望你来实现英文输入法单词联想功能。具体需求如下: 依据用户输入的单词前缀,从已输入的…...
【React 】入门Day01 —— 从基础概念到实战应用
目录 一、React 概述 二、开发环境创建 三、JSX 基础 四、React 的事件绑定 五、React 组件基础使用 六、组件状态管理 - useState 七、组件的基础样式处理 快速入门 – React 中文文档 一、React 概述 React 是什么 由 Meta 公司开发,是用于构建 Web 和原生…...
2024年9月总结及随笔之丢卡
1. 回头看 日更坚持了639天。 读《软件开发安全之道:概率、设计与实施》更新完成读《软件设计的要素》开更并更新完成读《构建可扩展分布式系统:方法与实践》开更并更新完成读《数据湖仓》开更并持续更新 2023年至2024年9月底累计码字1555996字&#…...
sql语法学习 sql各种语法 sql增删改查 数据库各种操作 数据库指令
sql语法学习 sql各种语法 sql增删改查 数据库各种操作 数据库指令 学习SQL语法时,理解其基本结构和用法是关键。下面是SQL语法的详细学习指南,涵盖了SQL的主要部分,包括查询、插入、更新、删除、表操作等。 1. 基本查询语法 SQL 的查询语句…...
鸡兔同笼,但是线性代数
灵感来自:bilibili,巨佬! 我们有 14 14 14 个头, 32 32 32 只脚,所有鸡和兔都没有变异,头和脚都完整,没有数错。还有什么 Bug 吗 小学奥数 假设全是鸡,则有 14 2 28 14 \time…...
01---java面试八股文——springboot---10题
01-你是怎么理解Spring Boot 的约定优于配置 约定优于配置是一种软件设计的范式,它的核心思想是减少软件开发人员对于配置项的维护,从而让开发人员更加聚焦在业务逻辑上。Spring Boot 就是约定优于配置这一理念下的产物,它类似于 Spring 框架…...
计算机毕业设计 二手图书交易系统的设计与实现 Java实战项目 附源码+文档+视频讲解
博主介绍:✌从事软件开发10年之余,专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ 🍅文末获取源码联系🍅 👇🏻 精…...
【进阶OpenCV】 (3)--SIFT特征提取
文章目录 sift特征提取一、基本原理二、特点三、代码实现1. 函数方法2. 检测图像中的关键点3. 绘制关键点4. 计算关键点描述符5. 输出特征坐标点 总结 sift特征提取 SIFT(Scale-Invariant Feature Transform,尺度不变特征变换)特征检测是一种…...
HarmonyOS/OpenHarmony Audio 实现音频录制及播放功能
关键词:audio、音频录制、音频播放、权限申请、文件管理 在app的开发过程中时常会遇见一些需要播放一段音频或进行语音录制的场景,那么本期将介绍如何利用鸿蒙 audio 模块实现音频写入和播放的功能。本次依赖的是 ohos.multimedia.audio 音频管理模块&am…...
css 中 ~ 符号、text-indent、ellipsis、ellipsis-2、text-overflow: ellipsis、::before的使用
1、~的使用直接看代码 <script setup> </script><template><div class"container"><p><a href"javascript:;">纪检委</a><a href"javascript:;">中介为</a><a href"javascript:…...
Activiti 工作流大致了解
一、什么是 Activiti 简而言之,就是系统的流程图,如:请假审批流程、账单审批流程等。 二、mysql与pom配置 mysql要使用jdbc:mysql://localhost:3306/activiti?autoReconnecttrue pom文件要添加关键依赖 <!--activiti核心依赖--> &…...
速盾:高防 CDN,网站安全的有力保障
在当今数字化时代,网站安全已成为企业和个人关注的焦点。随着网络攻击手段的不断升级,传统的安全防护措施已经难以满足需求。而高防 CDN(Content Delivery Network,内容分发网络)的出现,为网站安全提供了有…...
宝塔搭建nextcould 30docker搭建onlyoffic8.0
宝塔搭建nextcould 宝塔搭建nextcould可以参考这两个博文 我搭建的是30版本的nextcould,服务组件用的是下面这些,步骤是一样的,只是版本不一样而已 nginx 1.24.0 建议选择nginx,apache没成功。 MySQL 8.0以上都可以 php 8.2.…...
【源码+文档+调试讲解】交通信息管理系统
摘 要 智能交通信息管理系统是一种基于计算机技术的软件系统,旨在提高交通管理的效率和服务质量。通过该系统可以实现智能交通管理的全面管理和优化。智能交通信息管理系统具备集成管理功能。它能够整合智能交通管理的各个业务环节,包括个人中心、用户管…...
小阿轩yx-案例:Ansible剧本文件实践
小阿轩yx-案例:Ansible剧本文件实践 Playbook 介绍 什么是 playbook playbook 顾名思义,即剧本,现实生活中演员按照剧本表演在 ansible 中,由被控计算机表演,进行安装,部署应用,提供对外的服…...
【ShuQiHere】深入理解微架构(Microarchitecture):LC-3 的底层实现 ️
【ShuQiHere】🖥️ 微架构(Microarchitecture) 是计算机体系结构中的重要概念,它定义了如何将 指令集架构(Instruction Set Architecture, ISA) 转化为实际硬件。通过微架构,我们可以理解计算机…...
Ubuntu24.04.1系统下VideoMamba环境配置
文章目录 前言第一步:基本的环境创建第二步:causal-conv1d和mamba_ssm库的安装第三步:安装requirements.txt 前言 VideoMamba环境的配置折磨了我三天,由于Mamba对Cuda的版本有要求,因此配置环境的时候Cuda版本以及各种…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...
Linux中《基础IO》详细介绍
目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改,实现简单cat命令 输出信息到显示器,你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...
FOPLP vs CoWoS
以下是 FOPLP(Fan-out panel-level packaging 扇出型面板级封装)与 CoWoS(Chip on Wafer on Substrate)两种先进封装技术的详细对比分析,涵盖技术原理、性能、成本、应用场景及市场趋势等维度: 一、技术原…...
CppCon 2015 学习:REFLECTION TECHNIQUES IN C++
关于 Reflection(反射) 这个概念,总结一下: Reflection(反射)是什么? 反射是对类型的自我检查能力(Introspection) 可以查看类的成员变量、成员函数等信息。反射允许枚…...
Appium下载安装配置保姆教程(图文详解)
目录 一、Appium软件介绍 1.特点 2.工作原理 3.应用场景 二、环境准备 安装 Node.js 安装 Appium 安装 JDK 安装 Android SDK 安装Python及依赖包 三、安装教程 1.Node.js安装 1.1.下载Node 1.2.安装程序 1.3.配置npm仓储和缓存 1.4. 配置环境 1.5.测试Node.j…...
智能体革命:企业如何构建自主决策的AI代理?
OpenAI智能代理构建实用指南详解 随着大型语言模型(LLM)在推理、多模态理解和工具调用能力上的进步,智能代理(Agents)成为自动化领域的新突破。与传统软件仅帮助用户自动化流程不同,智能代理能够自主执行工…...
