RabbitMQ 在实际应用时要注意的问题

news2025/1/22 17:27:02

1. 幂等性保障

1.1 幂等性介绍

        幂等性是数学和计算机科学中某些运算的性质,它们可以被多次应⽤,⽽不会改变初始应⽤的结果.

应⽤程序的幂等性介绍

        在应⽤程序中,幂等性就是指对⼀个系统进⾏重复调⽤(相同参数),不论请求多少次,这些请求对系统的影响都是相同的效果.

        ⽐如数据库的 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也相同的消息.

        但是"最少⼀次",就会造成⼀个问题,消费端会收到重复的消息,也会造成对同⼀条消息进⾏多次处理.⼀ 些不重要的

        业务还好⼀点,对于重要的业务,如果不对重复的消息进⾏处理,会造成严重事故.

        ⽐如:当⽤户对⼀个订单付款之后,因为⽹络问题,付款成功的结果未返回给订单系统,当⽤户再次点击付款时,果系统未做幂等性处理,那就会造成两次扣款。

1.2 解决方案

        MQ 消费者的幂等性的解决⽅法,⼀般有以下⼏种:

全局唯⼀ ID

        1. 为每条消息分配⼀个唯⼀标识符,⽐如 UUID 或者 MQ 消息中的唯⼀ID,但是⼀定要保证唯⼀性. 

        2. 消费者收到消息后,先⽤该 id 判断该消息是否已经消费过,如果已经消费过,则放弃处理.

         3. 如果未消费过,消费者开始消费消息,业务处理成功后,把唯⼀ ID 保存起来(数据库或Redis等)

2. 顺序性保障

2.1 顺序性保障介绍

        消息的顺序性是指消费者消费的消息和⽣产者发送消息的顺序是⼀致的.

        ⽐如⽣产者发送的消息分别是 msg1,msg2,msg3,那么消费者也是按照msg1,msg2,msg3的顺序进⾏消费的.

        很多业务场景下,消息的消费是不⽤保证顺序的,⽐如使⽤ MQ 实现订单超时的处理.但有些业务场景, 能存在多个消息顺序处理的情况.⽐如⽤户信息修改,对同⼀个⽤户的同⼀个资料进⾏修改,需要保证消息的顺序      

        ⼀些资料显⽰ RabbitMQ 的消息能够保障顺序性,这是不严谨的.在不考虑消息丢失,⽹络故障等异常的情况下,如果只有⼀个消费者,最好也只有⼀个⽣产者的情况下,是可以保证消息的顺序性.如果有多个⽣产者同时发送消息,⽆法确定消息到达 RabbitMQ Broker 的前后顺序,也就⽆法验证消息的顺序性.哪些情况可能会打破 RabbitMQ 的顺序性呢?下⾯介绍⼏种常⻅的场景:

          1. 多个消费者:当队列配置了多个消费者时,消息可能会被不同的消费者并⾏处理,从⽽导致消息处理的顺序性⽆法保证.

        2. ⽹络波动或异常:在消息传递过程中,如果出现⽹络波动或异常,可能会导致消息确认(ACK)丢失,从⽽使得消息被重新⼊队和重新消费,造成顺序性问题.

        3. 消息重试:如果消费者在处理消息后未能及时发送确认,或者确认消息在传输过程中丢失,那么MQ 可能会认为消息未被成功消费⽽进⾏重试,这也可能导致消息处理的顺序性问题.

        4. 消息路由问题:在复杂的路由场景中,消息可能会根据路由键被发送到不同的队列,从⽽⽆法保证全局的顺序性.

        5. 死信队列:消息因为某些原因(如消费端拒绝消息)被放⼊死信队列,死信队列被消费时,⽆法保证消息的顺序和⽣产者发送消息的顺序⼀致

        包括但不仅限于以上⼏种情形会使 RabbitMQ 消息错序,如果要保证消息的顺序性,需要业务⽅使⽤ RabbitMQ 之后做进⼀步的处理

2.2 顺序性保障方案

        消息顺序性保障分为:局部顺序性保证和全局顺序性保证.

        局部顺序性通常指的是在单个队列内部保证消息的顺序.全局顺序性是指在多个队列或多个消费者之间保证消息的顺序.

        在实际应⽤中,全局顺序性很难实现,可以考虑使⽤业务逻辑来保证顺序性,⽐如在消息中嵌⼊序列号,并在消费端进⾏排序处理.相对⽽⾔,局部顺序性更常⻅,也更容易实现.

        RabbitMQ 作为⼀个分布式消息队列,主要优化的是吞吐量和可⽤性,⽽不是严格的顺序性保证.如果业务场景确实需要严格的消息顺序,可能需要在应⽤层⾯进⾏额外的设计和实现.

接下来说⼀下消息的顺序性保证的常⻅策略.

1. 单队列单消费者

        最简单的⽅法是使⽤单个队列,并由单个消费者进⾏处理.同⼀个队列中的消息是先进先出的,这是 RabbitMQ来帮助我们保证的.

2. 分区消费

        单个消费者的吞吐太低了,当需要多个消费者以提⾼处理速度时,可以使⽤分区消费.把⼀个队列分割成多个分区,每个分区由⼀个消费者处理,以此来保持每个分区内消息的顺序性.

        ⽐如⽤户修改资料后,发送⼀条⽤户资料消息.消费者在处理时,需要保证消息发送的先后顺序,但这种场合并不需要保证全局顺序.只需要保证同⼀个⽤户的消息顺序消费就可以.这时候就可以采 ⽤把消费按照⼀定的规则,分为多个区,每个分区由⼀个消费者处理 RabbitMQ 本⾝并不⽀持分区消费,需要业务逻辑去实现,或者借助 spring-cloud-stream 来实现

参考:https://docs.spring.io/spring-cloud-stream/reference/rabbit/rabbit_partitions.html

3. 消息确认机制

        使⽤⼿动消息确认机制,消费者在处理完⼀条消息后,显式地发送确认,这样 RabbitMQ 才会移除并继续发送下⼀条消息.

4. 业务逻辑控制

        在某些情况下,即使消息乱序到达,也可以在业务逻辑层⾯实现顺序控制.⽐如通过在消息中嵌⼊序列号,并在消费时根据这些信息来处理 RabbitMQ 本⾝并不保证全局的严格顺序性,特别是在分布式系统中.在实际应⽤开发中,根据具体的业 务需求,可能需要结合多种策略来实现所需要的顺序保证.

3. 消息积压问题

3.1 原因分析

        消息积压是指在消息队列(如 RabbitMQ )中,待处理的消息数量超过了消费者处理能⼒,导致消息在队列中不断堆积的现象.

通常有以下⼏种原因:

        1. 消息⽣产过快:在⾼流量或者⾼负载的情况下,⽣产者以极⾼的速率发送消息,超过了消费者的处理能⼒.

        2. 消费者处理能⼒不⾜:消费者处理消息的速度跟不上消息⽣产的速度,也会导致消息在队列中积压.

        可能原因有:

                1)消费端业务逻辑复杂,耗时⻓

                2)消费端代码性能低

                3)系统资源限制,如CPU、内存、磁盘I/O等也会限制消费者处理消息的效率.

                4)异常处理不当.消费者在处理消息时出现异常,导致消息⽆法被正确处理和确认.

3. ⽹络问题:因为⽹络延迟或不稳定,消费者⽆法及时接收或确认消息,最终导致消息积压

4. RabbitMQ 服务器配置偏低

        消息积压可能会导致系统性能下降,影响⽤户体验,甚⾄导致系统崩溃.因此,及时发现消息积压并解决对于维护系统稳定性⾄关重要.

3.2 解决方案

        遇到消息积压时,⾸先要分析消息积压造成的原因.根据原因来调整策略.主要从以下⼏个⽅⾯来解决:

1. 提高消费者效率

        a. 增加消费者实例数量,⽐如新增机器

        b. 优化业务逻辑,⽐如使⽤多线程来处理业务

        c. 设置 prefetchCount,当⼀个消费者阻塞时,消息转发到其他未阻塞的消费者.

        d. 消息发⽣异常时,设置合适的重试策略,或者转⼊到死信队列

2. 限制生产者速率.比如流量控制,限流算法等.

        a. 流量控制:在消息⽣产者中实现流量控制逻辑,根据消费者处理能⼒动态调整发送速率

        b. 限流:使⽤限流⼯具,为消息发送速率设置⼀个上限

        c. 设置过期时间.如果消息过期未消费,可以配置死信队列,以避免消息丢失,并减少对主队列的压⼒

3. 资源与配置优化.⽐如升级 RabbitMQ 服务器的硬件,调整 RabbitMQ 的配置参数等

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

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

相关文章

EXCEL+Python搞定数据处理(第一部分:Python入门-第1章:为什么要用Python为Excel编程)

参考资料: ExcelPython飞速搞定数据分析与处理,[瑞士] 费利克斯朱姆斯坦 著,中国工信出版社、人民邮电出版社出版(“Python for Excel, by Felix Zumstein (O’Reilly). Copyright 2021 Zoomer Analytics LLC, 978-1-492-08100-5”) 将不定…

MPLS VPN 部署与应用

一.简介 MPLS,称之为多协议标签交换,在九十年代中期被提出来,用于解决传统IP报文依赖查表转发而产生的瓶颈,现多用于VPN技术,MPLS报头封装在数据链路层之上,网络层之下。本文为结合了华为技术和新华三技术…

麒麟操作系统服务架构保姆级教程(十三)tomcat环境安装以及LNMT架构

如果你想拥有你从未拥有过的东西,那么你必须去做你从未做过的事情 之前咱们学习了LNMP架构,但是PHP对于技术来说确实是老掉牙了,PHP的市场占有量越来越少了,我认识一个10年的PHP开发工程师,十年工资从15k到今天的6k&am…

67,【7】buuctf web [HarekazeCTF2019]Avatar Uploader 2(未完成版)

进入靶场 和上一题一母同胞&#xff0c;先把上一题的答案拖进去看看 区别在于上一题这块直接显示了flag&#xff0c;这里并没有 看看源码 加载不出来&#xff0c;ctrlu <!-- 上传头像的提示信息&#xff0c;说明上传要求 --><p>Please upload a PNG image less th…

QD Laser携“Lantana”激光器参展SPIE光子学西部展2025,聚焦紧凑型设计

据悉&#xff0c;QD Laser公司将在2025年SPIE光子学西部展览会上展出其最新产品——世界最小一体化紧凑型可见光激光器“Lantana”。该展会将于1月28日至30日在旧金山的Moscone中心举行。 在展会期间&#xff0c;QD Laser公司将现场展示这款超小型、轻便设备—— “Lantana”。…

63,【3】buuctf web Upload-Labs-Linux 1

进入靶场 点击pass1 查看提示 既然是上传文件&#xff0c;先构造一句话木马&#xff0c;便于用蚁剑连接 <?php eval($_POST[123])?> 上传木马 文件后缀写为.php.jpg 右键复制图片地址 打开蚁剑连接 先点击测试连接&#xff0c;显示成功后&#xff0c;再点击添加即可 …

不重启JVM,替换掉已经加载的类

不重启JVM&#xff0c;替换掉已经加载的类 直接操作字节码 使用ASM框架直接操作class文件&#xff0c;在类中修改代码&#xff0c;然后retransform就可以了 下边是BTrace官方提供的一个简单例子&#xff1a; package com.sun.btrace.samples;import com.sun.btrace.annotati…

使用插件SlideVerify实现滑块验证

作者gitee地址&#xff1a;https://gitee.com/monoplasty/vue-monoplasty-slide-verify 使用步骤&#xff1a; 1、安装插件 npm install --save vue-monoplasty-slide-verify 2、在main.js中进行配置 import SlideVerify from vue-monoplasty-slide-verify; Vue.use(SlideV…

Kafka 和 MQ 的区别

1.概述 1.1.MQ简介 消息中间件&#xff0c;其实准确的叫法应该叫消息队列&#xff08;message queue&#xff09;&#xff0c;简称MQ。其本质上是个队列&#xff0c;有FIFO的性质&#xff0c;即first in first out&#xff0c;先入先出。 目前市场上主流的MQ有三款&#xff…

61,【1】BUUCTF WEB BUU XSS COURSE 11

进入靶场 左边是吐槽&#xff0c;右边是登录&#xff0c;先登录试试 admin 123456 admiin# 123456 admin"# 123456 不玩了&#xff0c;先去回顾下xss 回顾完就很尴尬了&#xff0c;我居然用SQL的知识去做xss的题 重来 吐槽这里有一个输入框&#xff0c;容易出现存储型…

CAN 网络介绍

背景 在T-Box 产品开发过程中&#xff0c;我们离不开CAN总线&#xff0c;因为CAN总线为我们提供了车身的相关数据&#xff0c;比如&#xff0c;车速、油耗、温度等。用于上报TSP平台&#xff0c;进行国标认证&#xff1b;也帮助我们进行车身控制&#xff0c;比如车门解锁/闭锁…

【C++】在线五子棋对战项目网页版

目录 1.Websocket 1.1.Websocket的简单认识 1.2.什么是轮询呢&#xff1f; 1.3.websocket协议切换过程 1.4.websocketpp库常用接口认识 1.5.websocketpp库搭建服务器流程 1.6.websocketpp库搭建服务器 2.mysqlclient库-接口认识 3.项目模块的划分&#xff1a; 4.项目…

《鸿蒙 HarmonyOS 应用开发从入门到精通(第 2 版)》学习笔记 ——HarmonyOS 环境搭建之安装DevEco Studio

作为一款开发工具&#xff0c;除了具有基本的代码开发、编译构建及调测等功能外&#xff0c;DevEco Studio还具有如下特点&#xff1a; 高效智能代码编辑&#xff1a;支持Java、XML、ArkTS、JS、C/C等语言的代码高亮、代码智能补齐、代码错误检查、代码自动跳转、代码格式化、…

2025年最新深度学习环境搭建:Win11+ cuDNN + CUDA + Pytorch +深度学习环境配置保姆级教程

本文目录 一、查看驱动版本1.1 查看显卡驱动1.2 显卡驱动和CUDA对应版本1.3 Pytorch和Python对应的版本1.4 Pytorch和CUDA对应的版本 二、安装CUDA三、安装cuDANN四、安装pytorch五、验证是否安装成功 一、查看驱动版本 1.1 查看显卡驱动 输入命令nvidia-smi可以查看对应的驱…

LAYA3.0 组件装饰器说明

原文 在LayaAirIDE中&#xff0c;如果想在IDE内展示组件脚本的属性&#xff0c;需要通过装饰器的规则来实现。下面分别介绍四种装饰器。 文章目录 一、regClass()二、property()2.1 组件属性的常规使用2.2 属性访问器的装饰器使用2.3 是否序列化保存2.4 组件属性是否在IDE中显…

PostIn安装教程

PostIn是一款国产开源免费的接口管理工具&#xff0c;包含项目管理、接口调试、接口文档设计、接口数据MOCK等模块&#xff0c;支持常见的HTTP协议、websocket协议等&#xff0c;支持免登陆本地接口调试&#xff0c;同时可以对项目进行灵活的成员权限、消息通知管理等。 1、服务…

RabbitMQ--延迟队列

&#xff08;一&#xff09;延迟队列 1.概念 延迟队列是一种特殊的队列&#xff0c;消息被发送后&#xff0c;消费者并不会立刻拿到消息&#xff0c;而是等待一段时间后&#xff0c;消费者才可以从这个队列中拿到消息进行消费 2.应用场景 延迟队列的应用场景很多&#xff0c;…

后端面试题分享第一弹(状态码、进程线程、TCPUDP)

后端面试题分享第一弹 1. 如何查看状态码&#xff0c;状态码含义 在Web开发和调试过程中&#xff0c;HTTP状态码是了解请求处理情况的重要工具。 查看状态码的步骤 打开开发者工具&#xff1a; 在大多数浏览器中&#xff0c;您可以通过按下 F12 键或右键单击页面并选择“检查…

网络通信---MCU移植LWIP

使用的MCU型号为STM32F429IGT6&#xff0c;PHY为LAN7820A 目标是通过MCU的ETH给LWIP提供输入输出从而实现基本的Ping应答 OK废话不多说我们直接开始 下载源码 LWIP包源码&#xff1a;lwip源码 -在这里下载 ST官方支持的ETH包&#xff1a;ST-ETH支持包 这里下载 创建工程 …

CSS笔记基础篇02——浮动、标准流、定位、CSS精灵、字体图标

黑马程序员视频地址&#xff1a; 前端Web开发HTML5CSS3移动web视频教程https://www.bilibili.com/video/BV1kM4y127Li?vd_source0a2d366696f87e241adc64419bf12cab&spm_id_from333.788.videopod.episodes&p70https://www.bilibili.com/video/BV1kM4y127Li?vd_source…