RabbitMQ应用问题

news2024/11/6 22:24:21

1. 幂等性保障

1.1 介绍

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

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

⽐如数据库的 select 操作. 不同时间两次查询的结果可能不同, 但是这个操作是符合幂等性的.

幂等性指的是对资源的影响, ⽽不是返回结果. 查询操作对数据资源本⾝不会产⽣影响, 之所以结果不同, 可能是因为两次查询之间有其他操作对资源进⾏了修改.

⽐如 i++ 这个操作, 就是⾮幂等性的. 如果调⽤⽅没有控制好逻辑, ⼀次流程重复调⽤好⼏次, 结果 就会不同.

MQ的幂等性介绍

对于MQ⽽⾔, 幂等性是指同⼀条消息, 多次消费, 对系统的影响是相同的.

比如,接口幂等性:

多次调用支付接口(同一个订单,同样的参数),对于系统的影响是一样的(只能支付一次)

⼀般消息中间件的消息传输保障分为三个层级:

  • At most once:最多⼀次. 消息可能会丢失,但绝不会重复传输.
  •  At least once:最少⼀次. 消息绝不会丢失,但可能会重复传输.
  • Exactly once:恰好⼀次. 每条消息肯定会被传输⼀次且仅传输⼀次.(RabbitMQ不⽀持)

在业务使⽤中, 对于可靠性要求⽐较⾼的场景, 建议使⽤"最少⼀次", 以防⽌消息丢失. "最多⼀次" 会因为消息发送过程中, ⽹络问题, 消费出现异常等种种原因, 导致消息丢失.

以下场景可能会导致消息发送重复:

  • 发送时消息重复: 当⼀条消息已被成功发送到服务端并完成持久化, 此时出现了⽹络闪断或者客⼾端宕机, 导致服务端对客⼾端应答失败. 如果此时Producer意识到消息发送失败并尝试再次发送消息, Consumer后续会收到两条内容相同并且Message ID也相同的消息.
  • 投递时消息重复: 消息消费的场景下, 消息已投递到Consumer并完成业务处理, 当客⼾端给服务端反馈应答的时候⽹络闪断. 为了保证消息⾄少被消费⼀次, 云消息队列 RabbitMQ 版的服务端将在⽹络恢复后再次尝试投递之前已被处理过的消息, Consumer后续会收到两条内容相同并且 Message ID也相同的消息.

但是"最少⼀次", 就会造成⼀个问题, 消费端会收到重复的消息, 也会造成对同⼀条消息进⾏多次处理. ⼀些不重要的业务还好,对于重要的事务,如果不对重复的消息进⾏处理, 会造成严重事故.

⽐如:

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

1.2 解决

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

全局唯⼀ID

  • 为每条消息分配⼀个唯⼀标识符, ⽐如UUID或者MQ消息中的唯⼀ID,但是⼀定要保证唯⼀性.
  • 消费者收到消息后, 先⽤该id判断该消息是否已经消费过, 如果已经消费过, 则放弃处理.
  • 如果未消费过, 消费者开始消费消息, 业务处理成功后, 把唯⼀ID保存起来(数据库或Redis等) 

可以使⽤Redis 的原⼦性操作setnx(set if not exists)来保证幂等性, 将唯⼀ID作为key放到redis中 (SETNX messageID 1) .

返回1, 说明之前没有消费过, 正常消费. 返回0, 说明这条消息之前已消费过, 抛弃.

业务逻辑判断

在业务逻辑层⾯实现消息处理的幂等性

例如:

检查数据库中是否已存在相关数据记录, 或者使⽤乐观锁机制来避免更新已被其他事务更改的数据, 再或者在处理消息之前, 先检查相关业务的状态, 确保消息对应的操作尚未执⾏, 然后才进⾏处理, 具体根据业务场景来处理

2. 顺序性保障

2.1 介绍 

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

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

很多业务场景下, 消息的消费是不⽤保证顺序的, ⽐如使⽤MQ实现订单超时的处理.

但有些业务场景, 可能存在多个消息顺序处理的情况. ⽐如⽤⼾信息修改, 对同⼀个⽤⼾的同⼀个资料进⾏修改, 需要保证消息的顺序.(修改name为张山,修改name为李四)

⼀些资料显⽰RabbitMQ的消息能够保障顺序性, 这是不严谨的.

在不考虑消息丢失, ⽹络故障等异常的情况下, 如果只有⼀个消费者, 最好也只有⼀个⽣产者的情况下, 是可以保证消息的顺序性.

如果有多个⽣产者同时发送消息, ⽆法确定消息到达RabbitMQ Broker的前后顺序, 也就⽆法验证消息的顺序性.

下面是几种常见的场景:

  • 多个消费者: 当队列配置了多个消费者时, 消息可能会被不同的消费者并⾏处理, 从⽽导致消息处理的顺序性⽆法保证.
  • ⽹络波动或异常: 在消息传递过程中, 如果出现⽹络波动或异常, 可能会导致消息确认(ACK) 丢失, 从⽽使得消息被重新⼊队和重新消费, 造成顺序性问题.
  • 消息重试:如果消费者在处理消息后未能及时发送确认, 或者确认消息在传输过程中丢失, 那么MQ 可能会认为消息未被成功消费⽽进⾏重试, 这也可能导致消息处理的顺序性问题.
  • 消息路由问题: 在复杂的路由场景中, 消息可能会根据路由键被发送到不同的队列, 从⽽⽆法保证全局的顺序性.
  • 死信队列: 消息因为某些原因(如消费端拒绝消息)被放⼊死信队列, 死信队列被消费时, ⽆法保证消息的顺序和⽣产者发送消息的顺序⼀致 

2.2 解决 

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

局部顺序性通常指的是在单个队列内部保证消息的顺序.

全局顺序性是指在多个队列或多个消费者之间保证消息的顺序.(难以实现)

mq消息的顺序性保证的常见策略:

单队列单消费者

最简单的⽅法是使⽤单个队列(合成一个队列), 并由单个消费者进⾏处理.

同⼀个队列中的消息是先进先出的, 这是 RabbitMQ来帮助我们保证的.

分区消费(rabbitmq不支持)

单个消费者的吞吐太低了, 当需要多个消费者以提⾼处理速度时, 可以使⽤分区消费.

把⼀个队列分割成多个分区, 每个分区由⼀个消费者处理, 以此来保持每个分区内消息的顺序性.

举个例子:根据订单ID进行分区

把同一个订单的消息发送给同一个队列,由同一个消费者进行消费

消息确认机制

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

业务逻辑控制

在某些情况下, 即使消息乱序到达, 也可以在业务逻辑层⾯实现顺序控制.

⽐如通过在消息中嵌⼊序列号, 并在消费时根据这些信息来处理

RabbitMQ本⾝并不保证全局的严格顺序性, 特别是在分布式系统中. 在实际应⽤开发中, 根据具体的业务需求, 可能需要结合多种策略来实现所需要的顺序保证.

 

3. 消息积压问题

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

3.1 原因

  • 1)消息⽣产过快: 在⾼流量或者⾼负载的情况下, ⽣产者以极⾼的速率发送消息, 超过了消费者的处理能⼒.
  • 2)消费者处理能⼒不⾜: 消费者处理处理消息的速度跟不上消息⽣产的速度, 也会导致消息在队列中积压.

    2)可能原因有:

  • 消费端业务逻辑复杂, 耗时⻓
  • 消费端代码性能低
  • 系统资源限制, 如CPU、内存、磁盘I/O等也会限制消费者处理消息的效率.
  • 异常处理处理不当. 消费者在处理消息时出现异常, 导致消息⽆法被正确处理和确认.
  • 3)⽹络问题: 因为⽹络延迟或不稳定, 消费者⽆法及时接收或确认消息, 最终导致消息积压
  • 4)RabbitMQ 服务器配置偏低

3.2 解决

1. 提⾼消费者效率

  • a. 增加消费者实例数量, ⽐如新增机器
  • b. 优化业务逻辑, ⽐如使⽤多线程来处理业务
  • c. 设置prefetchCount, 当⼀个消费者阻塞时, 消息转发到其他未阻塞的消费者.
  • d. 消息发⽣异常时, 设置合适的重试策略, 或者转⼊到死信队列

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

  • a. 流量控制: 在消息⽣产者中实现流量控制逻辑, 根据消费者处理能⼒动态调整发送速率
  • b. 限流: 使⽤限流⼯具, 为消息发送速率设置⼀个上限
  • c. 设置过期时间. 如果消息过期未消费, 可以配置死信队列, 以避免消息丢失, 并减少对主队列的压⼒

3. 资源与配置优化.

  • ⽐如升级RabbitMQ服务器的硬件, 调整RabbitMQ的配置参数等 

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

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

相关文章

游戏引擎中的颜色科学

游戏引擎中的渲染组件的作用是生成一个二维图片,在特定的时间从给定的视点观察的方向看到的一个三维空间的状态。他们的生成每一张图片都会被称为帧,他们生成的速度称为帧率。 像素 在每一帧中,游戏引擎的视觉输出基本上是一大堆彩色像素&a…

css中pointer-events:none属性对div里面元素的鼠标事件的影响

文章目录 前倾提要当没有设置属性pointer-events时候结果 当子元素设置了pointer-events: none修改后的代码结果如下所示 当父元素设置了pointer-events: none若两个div同级也就是兄弟级 前倾提要 在gis三维开发的地图组件上放一个背景图片,左右两侧的颜色渐变等&a…

中科蓝汛GPIO操作说明

概述 本篇文章介绍如何使用中科蓝汛AB5681,GPIO管脚使用说明。 一、第一种写法 1)、GPIO配置输入模式 //内部上拉 GPIOBDE | BIT(4); //数字IO使能: 0为模拟IO, 1 为数字IO GPIOBDIR | BIT(4); //控制IO的方向: 0为输出, 1为输入. GPIOBFEN &…

Kotlin 协程使用及其详解

Kotlin协程,好用,但是上限挺高的,我一直感觉自己就处于会用,知其然不知其所以然的地步。 做点小总结,比较浅显。后面自己再继续补充吧。 一、什么是协程? Kotlin 协程是一种轻量级的并发编程方式&#x…

LabVIEW 离心泵机组故障诊断系统

开发了一套基于LabVIEW图形化编程语言设计的离心泵机组故障诊断系统。系统利用先进的数据采集技术和故障诊断方法,通过远程在线监测与分析,有效提升了离心泵的预测性维护能力,保证了石油化工生产的连续性和安全性。 项目背景及意义 离心泵作…

线程函数和线程启动的几种不同形式

线程函数和线程启动的几种不同形式 在C中&#xff0c;线程函数和线程启动可以通过多种形式实现。以下是几种常见的形式&#xff0c;并附有相应的示例代码。 1. 使用函数指针启动线程 最基本的方式是使用函数指针来启动线程。 示例代码&#xff1a; #include <iostream&g…

辐射传输方程的分解

Decomposition of the Boundary Value Problem for Radiative Transfer Equation of MODIS and MISR instruments 0.Notions Let L L L be the straming-collision operator, and S S S is scattering operator: L I Ω ⋅ ∇ I ( r , Ω ) σ ( r , Ω ) I ( r , Ω ) S…

智会智展,活动必备

智会智展 APP 各大应用市场均可下载统一链接https://m.malink.cn/s/r6nQVf

Hive操作库、操作表及数据仓库的简单介绍

数据仓库和数据库 数据库和数仓区别 数据库与数据仓库的区别实际讲的是OLTP与OLAP的区别 操作型处理(数据库)&#xff0c;叫联机事务处理OLTP&#xff08;On-Line Transaction Processing&#xff09;&#xff0c;也可以称面向用户交易的处理系统&#xff0c;它是针对具体业务…

如何选择适合小团队的项目管理工具?免费与开源软件推荐

目录 一、小团队项目管理工具的重要性 二、热门项目管理工具介绍 &#xff08;一&#xff09;禅道 &#xff08;二&#xff09;Trello &#xff08;三&#xff09;Asana &#xff08;四&#xff09;JIRA 三、免费项目管理软件推荐 &#xff08;一&#xff09;ES 管理器 …

kafka如何获取 topic 主题的列表?

大家好&#xff0c;我是锋哥。今天分享关于【kafka如何获取 topic 主题的列表&#xff1f;】面试题&#xff1f;希望对大家有帮助&#xff1b; kafka如何获取 topic 主题的列表&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在Kafka中&#xff0c;可以…

Maven详解—(详解Maven,包括Maven依赖管理以及声明周期,Maven仓库、idea集成Maven)

文章目录 Maven详解一.初始Maven1.1 概述1.2 作用 二.Maven模型2.1 概述2.2 构建生命周期/阶段2.3 项目对象模型2.4 依赖管理模型 三.Maven仓库四.Maven安装4.1 下载4.2 安装步骤 五.Idea集成Maven Maven详解 一.初始Maven 1.1 概述 Maven是Apache旗下的一个开源项目&#x…

虚拟滚动 - 从基本实现到 Angular CDK

简介 在大数据列表的处理上&#xff0c;虚拟滚动是一种优化性能的有效方式。本篇文章将详细介绍两种常见的虚拟滚动实现方式&#xff1a;使用 transform 属性和 Intersection Observer。重点讲解如何通过 transform 属性实现高效的虚拟滚动&#xff0c;并对比Angular CDK中的实…

Spring Boot 配置文件启动加载顺序

前言 Spring Boot的启动加载顺序是一个涉及多个步骤和组件的过程。Spring Boot通过一系列默认设置简化了应用程序的配置&#xff0c;使得开发者能够快速地搭建和部署应用。为了实现这一目标&#xff0c;Spring Boot采用了一种分层和优先级机制来加载配置文件。 一、Spring Bo…

C# Modbus RTU通讯回顾

涉及技术&#xff1a; 1.使用NMdbus4 库 2.ushort[]转int 记得之前刚学习的时候&#xff0c;是ushort[] → Hex字符串→byte[] → 翻转byte[] →BitConverter.ToInt32()&#xff0c;饶了一大圈&#xff1b;实际上可以直接转&#xff1b;这里也有小细节&#xff1a;使用BitCo…

HFSS学习笔记(五)金属过孔、复制模型带激励等问题(持续更新...)

HFSS学习笔记&#xff08;五&#xff09;金属过孔、复制模型带激励等问题&#xff08;持续更新…&#xff09; 一、金属过孔设计 方法一&#xff1a;用介质减去金属圆柱体&#xff0c;然后再添加金属圆柱体 方法二&#xff1a;嵌入金属圆柱 圆柱过孔选择材料为“copper” HFS…

Late Chunking×Milvus:如何提高RAG准确率

01. 背景 在RAG应用开发中&#xff0c;第一步就是对于文档进行chunking&#xff08;分块&#xff09;&#xff0c;高效的文档分块&#xff0c;可以有效的提高后续的召回内容的准确性。而对于如何高效的分块是个讨论的热点&#xff0c;有诸如固定大小分块&#xff0c;随机大小分…

大屏可视化:舞动数据与美观的“设计秘籍”

大屏可视化鉴赏&#xff1a;踏入软件系统产品设计之旅&#xff0c;让我们一同鉴赏那些闪耀在智慧农业、智慧园区、智慧社区及智慧港口等领域的大屏可视化杰作。每一帧画面&#xff0c;都是科技与创新的完美融合&#xff0c;数据跃然屏上&#xff0c;智慧触手可及。 >> 数…

基于STM32的智能声音跟随小车设计

引言 本项目基于STM32微控制器设计了一个智能声音跟随小车&#xff0c;通过集成麦克风阵列实现声音源定位和跟随功能。该系统可以检测环境中的声音信号&#xff0c;如手掌拍击声或语音指令&#xff0c;驱动小车向声源方向移动。项目涉及硬件设计、声音信号处理算法以及电机控制…

Bruno解决SSL验证问题

在测试接口的时候&#xff0c;我使用的是Bruno这个软件&#xff0c;开源离线的API测试软件。 主页是这样子的 今天在测试一个HTTPS的接口时候&#xff0c;因为这个HTTPS接口是用的是自签证书&#xff0c;所以就报错误了。 Error invoking remote method send-http-request: …