RabbitMQ应用问题

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.mzph.cn/bicheng/59476.shtml

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

相关文章

HTB:Sense[WriteUP]

目录 连接至HTB服务器并启动靶机 1.What is the name of the webserver running on port 80 and 443 according to nmap? 使用nmap对靶机TCP端口进行开放扫描 2.What is the name of the application that presents a login screen on port 443? 使用浏览器访问靶机80端…

【LeetCode每日一题】——802.找到最终的安全状态

文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时空频度】九【代码实现】十【提交结果】 一【题目类别】 图 二【题目难度】 中等 三【题目编号】 802.找到最终的安全状态 四【题目描述】 有一个有…

stm32使用串口的轮询模式,实现数据的收发

------内容以b站博主keysking为原型,整理而来,用作个人学习记录。 首先在STM32CubeMX中配置 前期工作省略,只讲重点设置。 这里我配置的是USART2的模式。 会发现,PA2和PA3分别是TX与RX,在连接串口时需要TX对RX&…

C++上机实验|继承与派生编程练习

1.实验目的 (1) 掌握派生与继承的概念与使用方法 (2) 运用继承机制对现有的类进行重用。 (3) 掌握继承中的构造函数与析构函数的调用顺序, (4) 为派生类设计合适的构造函数初始化派生类。 (5) 深入理解继承与组合的区别。 2.实验内容 设计一个人员类 person 和一个日期类 da…

【MySQL】 运维篇—故障排除与性能调优:案例分析与故障排除练习

理论知识及概念介绍 1. 故障排除的重要性 无论是电商平台、社交网络还是企业管理系统,数据库的稳定性和性能直接影响到用户体验和业务运作。因此,及时发现并解决数据库故障是确保系统高可用性和可靠性的关键。 2. 应用场景 电商平台:在大促…

【STL_list 模拟】——打造属于自己的高效链表容器

一、list节点 ​ list是一个双向循环带头的链表&#xff0c;所以链表节点结构如下&#xff1a; template<class T>struct ListNode{T val;ListNode* next;ListNode* prve;ListNode(int x){val x;next prve this;}};二、list迭代器 2.1、list迭代器与vector迭代器区别…

冒泡排序、选择排序、计数排序、插入排序、快速排序、堆排序、归并排序JAVA实现

常见排序算法实现 冒泡排序、选择排序、计数排序、插入排序、快速排序、堆排序、归并排序JAVA实现 文章目录 常见排序算法实现冒泡排序选择排序计数排序插入排序快速排序堆排序归并排序 冒泡排序 冒泡排序算法&#xff0c;对给定的整数数组进行升序排序。冒泡排序是一种简单…

如何高效集成每刻与金蝶云星空的报销单数据

每刻报销单集成到金蝶云星空的技术实现 在企业日常运营中&#xff0c;费用报销和付款申请是两个至关重要的环节。为了提升数据处理效率和准确性&#xff0c;我们采用了轻易云数据集成平台&#xff0c;将每刻系统中的报销单数据无缝对接到金蝶云星空的付款申请单中。本案例将详…

陪玩app小程序开发案例源码核心功能介绍

‌陪玩系统‌是一种基于互联网技术的服务平台&#xff0c;旨在为用户提供游戏陪玩、语音聊天、社交互动等功能。陪玩系统通常包括以下几个核心功能&#xff1a; ‌游戏约单‌&#xff1a;用户可以通过陪玩系统发布游戏约单&#xff0c;寻找合适的陪玩伙伴一起进行游戏&#xf…

【题解】【排序】—— [NOIP2017 普及组] 图书管理员

【题解】【排序】—— [NOIP2017 普及组] 图书管理员 [NOIP2017 普及组] 图书管理员题目背景题目描述输入格式输出格式输入输出样例输入 #1输出 #1 提示 1.思路解析2.AC代码 [NOIP2017 普及组] 图书管理员 通往洛谷的传送门 题目背景 NOIP2017 普及组 T2 题目描述 图书馆中…

WPF+MVVM案例实战(十七)- 自定义字体图标按钮的封装与实现(ABC类)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1、案例效果1、按钮分类2、ABC类按钮实现1、文件创建2、字体图标资源3、自定义依赖属性4、按钮特效样式实现 3、按钮案例演示1、页面实现与文件创建2、依赖注入3 运…

《Qwen2-VL》论文精读【下】:发表于2024年10月 Qwen2-VL 迅速崛起 | 性能与GPT-4o和Claude3.5相当

1 前言 《Qwen2-VL》论文精读【上】&#xff1a;发表于2024年10月 Qwen2-VL 迅速崛起 | 性能与GPT-4o和Claude3.5相当 上回详细分析了Qwen2-VL的论文摘要、引言、实验&#xff0c;下面继续精读Qwen2-VL的方法部分。 文章目录 1 前言2 方法2.1 Model Architecture2.2 改进措施2…

TypeScript延迟执行工具类

TypeScript延迟执行工具类 在前端开发中&#xff0c;我们经常需要处理一些延迟执行、防抖和节流的场景。今天介绍一个实用的Delay工具类&#xff0c;它提供了这些常用的延迟执行功能。 文章目录 TypeScript延迟执行工具类0、完整代码1. 基础延迟执行sleep方法execute方法 2. 防…

RustRover加载Rust项目报错

问题描述&#xff1a; 昨天还可以正常使用的RustRover今天打开Rust项目一直报错&#xff1a; warning: spurious network error (3 tries remaining): [7] Couldnt connect to server (Failed to connect to 127.0.0.1 port 51342 after 105750 ms: Couldnt connect to server…

C语言---文件操作万字详细分析(6)

文件操作 到这里&#xff0c; C语言所有知识点&#xff0c; 就告已段落了&#xff0c; 虽然知识点到这里结束了&#xff0c; 但我想&#xff0c; 我们的编程之路也可能刚刚开始&#xff0c; 这些知识&#xff0c; 是我们在创造伟大事物时&#xff0c; 必不可少的基础&#xff…

回溯——3、5升杯倒4升水

回溯应用 接前面书上说数学浅谈最大公约数g c d ( a , b ) = x ∗ a + y ∗ b gcd(a,b)=x*a+y*b gcd(a,b)=x∗a+y∗bP 3 2 = 6 P_{3}^{2}=6 P32​=6只要一杯8升水代码一般回溯方法的程序结构打印接前面 递归的改造——间隔挑硬币打印所挑选的硬币需要用到回溯。但书上的回溯没…

clickhouse 安装配置

1.clickhouse官网下载安装包&#xff1a; 官网下载地址&#xff1a; https://packages.clickhouse.com/tgz/ 下载四个tgz文件&#xff1a; 1 clickhouse-common-static 2 clickhouse-common-static-dbg 3 clickhouse-server 4 clickhouse-client 2 安装上面1到4的顺序依…

STM32学习记录---jlink使用

SEGGER J-Flash V6.82g下载程序&#xff1b; 硬件&#xff1a;ARM仿真器 swd口 过程&#xff1a; 1.打开软件&#xff0c;会提示是否打开上一次的.jflash文件&#xff1b; 2.新建工程 3.选择器件&#xff0c;找不到&#xff0c;可以找相近的或者相近的核心 4.选择完成&…

IPsec传输模式与隧道模式的深度解析及应用实例

随着网络安全威胁的日益严峻&#xff0c;IPsec作为网络层安全协议&#xff0c;其传输模式与隧道模式的选择对确保通信安全至关重要。本文旨在深入探讨这两种模式的差异&#xff0c;并通过实际案例展示其应用。 一、传输模式和隧道模式的详细描述 传输模式&#xff1a; 应用场景…

A014-基于Spring Boot的家电销售展示平台设计与实现

&#x1f64a;作者简介&#xff1a;在校研究生&#xff0c;拥有计算机专业的研究生开发团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339; 赠送计算机毕业设计600…