RabbitMQ 应用问题

在这里插入图片描述

文章目录

  • 1. 幂等性保障
    • 什么是幂等性
    • MQ 的幂等性
    • 如何处理消息重复的问题
      • 1. 全局唯一ID
      • 2. 业务逻辑判断
  • 2. 顺序性保障
    • 什么是顺序性保障
    • 什么情况会打破RabbitMQ的顺序性
    • 顺序性保障方案
  • 3. 消息积压
    • 什么是消息积压
    • 造成消息积压的原因
    • 解决消息积压的方案
  • 结论

1. 幂等性保障

什么是幂等性

幂等性(Idempotence)是一个数学概念,但在计算机科学和编程领域,特别是分布式系统、数据库操作、HTTP请求处理等场景中,它有着特别重要的意义。在数学上,幂等性指的是一个操作(或函数)多次执行与一次执行的效果相同。换句话说,如果某个操作或函数在给定参数上多次执行,其最终结果与仅执行一次时相同,则称该操作或函数具有幂等性。

在计算机科学中,幂等性主要应用于以下几个方面:

  1. 数据库操作:如SQL中的INSERT INTO … ON DUPLICATE KEY UPDATE语句,或者在执行UPDATE操作时,如果更新条件没有匹配到任何行,则操作不会对数据库产生任何影响,因此可以视为幂等的。对于INSERT操作,如果数据库表的主键或唯一索引不允许重复值,则重复的INSERT操作会失败,这本身不是幂等的,但可以通过特定的数据库特性或应用逻辑来实现幂等性。
  2. HTTP请求:在HTTP协议中,GET、PUT、DELETE等方法被认为是幂等的。GET请求用于读取资源,多次读取不会改变资源状态;PUT请求用于替换资源,多次提交相同的资源表示不会改变资源的最终状态;DELETE请求用于删除资源,多次删除同一个已删除的资源也不会产生额外影响。相比之下,POST请求通常不是幂等的,因为它通常用于创建新的资源,多次提交相同的POST请求可能会导致资源的重复创建。
  3. 分布式系统:在分布式系统中,由于网络延迟、节点故障等因素,相同的操作可能会被重复执行。设计系统时,确保关键操作具有幂等性可以大大简化错误处理和重试逻辑,提高系统的健壮性和可靠性。
  4. 消息队列和消息中间件:在消息队列系统中,确保消息处理的幂等性对于避免数据重复处理至关重要。这通常通过消息的唯一标识符(如UUID)来实现,当消息中间件或消费者接收到重复的消息时,可以基于这个唯一标识符来跳过重复的处理。

MQ 的幂等性

对于 MQ 而言,幂等性是指同一条消息,多次消费,对于系统的影响和一次消费是相同的。

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

  1. At most once:最多一次,消息可能会丢失,但绝不会重复传输
  2. At least once:最少一次,消息绝不会丢失,但可能会重复传输
  3. Exactly once:恰好一次,每条消息肯定会被传输一次且仅传输一次

RabbitMQ 支持“最多一次”和“最少一次”,对于“恰好一次”,不止是 RabbitMQ,大部分的消息中间件都无法实现“恰好一次”。要想实现“恰好一次“,就需要牺牲性能来实现。

那么如何选择是使用”最少一次“还是”最多一次“呢?在业务使用中,对于消息可靠性要求比较高的场景,建议使用”最少一次“,以防止消息丢失;而对于消息可靠性要求不高的场景就可以使用”最多一次“,”最多一次“的消息传输很可能会因为网络传输、消费异常等问题而导致丢失。

那么最少一次有什么代价呢?代价就是需要消耗更多的性能和消息重复,消耗更高的性能就是判断是否需要重复传输以及重复传输。而消息的重复可能会导致严重的事故,例如用户付款成功之后的消息处理,需要将用户的余额扣除,如果次数因为网络等问题,导致消费者这里出现了重复的此消息,那么就会导致用户多次扣款。那么什么原因会导致消息的重复呢?

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

在这里插入图片描述
那么如何处理消息重复的问题呢?

如何处理消息重复的问题

1. 全局唯一ID

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

2. 业务逻辑判断

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

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

2. 顺序性保障

什么是顺序性保障

RabbitMQ顺序保障主要指的是确保消息在RabbitMQ中被消费的顺序与生产者发送的顺序一致。比如 生产者发送消息的顺序为msg1,msg2,msg3,那么消费者也是应该按照msg1,msg2,msg3的顺序进行消费的。

虽然在很多的业务场景下,消息的消费顺序不不需要做出保障的,但是对于一些场景却需要对消费者消费消息的顺序做出保障,例如用户修改用户信息,如果用户短时间内修改了多次,那么最终就需要以最后一次修改作为修改的结果,但是如果我们的消费者消费的顺序和生产者生产消息的顺序不同的时候就会出现最终的结果不是我们预期的结果。

RabbitMQ本身并不直接提供消息顺序性的保证机制,因为RabbitMQ的设计初衷是支持高并发和消息的高可用性,允许消息被发送到多个消费者进行并行处理。但在实际应用中,可以通过一些策略和方法来实现消息的顺序保障。

什么情况会打破RabbitMQ的顺序性

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

顺序性保障方案

消息顺序性保障分为:局部顺序性保证和全局顺序性保证。 局部顺序性通常指的是在单个队列内部保证消息的顺序。全局顺序性是指在多个队列或多个消费者之间保证消息的顺序。

在实际应用中,全局顺序性很难实现,可以考虑使用业务逻辑来保证顺序性,比如在消息中嵌入序列号,并在消费端进行排序处理。相对而言,局部顺序性更常见,也更容易实现。

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

接下来说一下消息的顺序性保证的常见策略:

  1. 单一消费者模式:
    将队列设置为只允许一个消费者连接,这样可以确保消息按照发送的顺序被消费。但这种方式限制了消息的并行处理能力,无法实现高吞吐量。
  2. 消息分区(Message Partitioning):
    根据消息中的某个特定属性(如订单ID、用户ID等)将消息分发到不同的队列中,每个队列由一个消费者处理。这样可以保证每个队列内的消息顺序,但整体系统的消息处理仍然是并行的。
    在RabbitMQ中,这通常通过交换机(Exchange)和绑定键(Routing Key)来实现,将具有相同属性的消息路由到同一个队列。
  3. 业务逻辑控制:
    在消息处理过程中,通过业务逻辑来确保消息的顺序性。例如,可以为每个消息引入一个序号,并在消费时检查序号的连续性。
  4. 手动消息确认机制:
    在RabbitMQ中,消费者可以显式地发送消息确认,告知RabbitMQ该消息已被成功处理。只有在收到确认后,RabbitMQ才会从队列中移除该消息,并继续处理下一个消息。通过这种方式,可以控制消息的处理顺序。
  5. 使用优先级队列:
    RabbitMQ支持优先级队列,可以在创建队列时设置其最大优先级。生产者可以为每个消息设置优先级,消费者在消费时会优先处理高优先级的消息。但需要注意的是,优先级队列并不能完全保证消息的顺序性,只是在一定程度上影响消息的处理顺序。
  6. 结合其他中间件或框架:
    在某些情况下,可以结合使用其他中间件或框架(如Spring Cloud Stream)来实现消息的分区消费和顺序保障。这些框架提供了更高级别的抽象和配置选项,可以更容易地实现复杂的消息处理场景。

3. 消息积压

什么是消息积压

RabbitMQ消息积压(Message Backlog 或 Message Accumulation)是指RabbitMQ中的消息队列中积累了大量未被消费的消息,导致这些消息在队列中等待处理的时间过长。这种情况通常发生在消费者处理消息的速度跟不上生产者发送消息的速度时,或者由于某些原因导致消费者无法正常工作(如消费者崩溃、网络问题、资源限制等)。

当RabbitMQ发生消息积压时,可能会带来一系列问题,如消息处理延迟增加、系统响应变慢、甚至可能导致系统崩溃。消息积压还可能影响消息的顺序性,因为后发送的消息可能会比先发送的消息更早被处理(如果使用了多个消费者或队列)。

造成消息积压的原因

  1. 消费者处理速度慢:当消费者处理消息的速度跟不上生产者发送消息的速度时,消息会在队列中堆积。这可能是由于消费者本身的性能瓶颈、处理逻辑复杂或资源分配不当等原因造成的。
  2. 队列配置不合理:队列的长度限制设置不合理,或者队列的持久化设置不当,都可能导致消息积压。例如,如果队列的容量设置过小,而生产者发送的消息量又很大,那么一旦队列达到容量上限,新产生的消息就会因为无法入队而积压。
  3. 网络问题:网络延迟或中断可能导致消费者无法及时从RabbitMQ服务器获取消息,从而造成消息积压。尤其是在分布式系统中,网络问题往往是导致消息积压的常见原因之一。
  4. 服务器配置偏低:在高流量情况下,RabbitMQ服务器的配置可能不足以处理快速增长的消息量。这包括服务器的CPU、内存、网络带宽等资源不足,无法支撑高并发的消息处理需求。
  5. 消费者故障:消费者进程崩溃或处理逻辑错误,导致无法继续消费消息。在这种情况下,如果系统没有相应的容错和恢复机制,那么积压的消息将无法被及时处理。
  6. 程序逻辑设计问题:生产者持续生产消息,而消费者由于逻辑设计不当,无法有效消费消息。例如,消费者可能因为某些条件判断错误而拒绝处理某些消息,或者因为处理流程设计不合理而导致消息处理效率低下。
  7. 流量激增:在某些情况下,由于业务需求的突然变化或外部事件的触发,系统可能会在短时间内接收到大量的消息。如果系统没有做好相应的准备和扩容措施,那么很容易导致消息积压。

解决消息积压的方案

一、增加消费者数量和提升消费者处理能力

  1. 增加消费者数量:
  • 通过增加消费者的数量,可以分摊消息处理的负载,从而提高整体的消息处理速度。
  • RabbitMQ支持多个消费者同时从同一个队列中消费消息,实现并行处理。
  1. 提升消费者处理能力:
  • 优化消费者的代码逻辑,减少单个消息的处理时间。
  • 使用多线程或异步处理机制,提高消费者的并发处理能力。
  • 考虑升级消费者服务器的硬件资源,如增加CPU、内存等,以提升处理性能。

二、调整RabbitMQ配置和架构

  1. 调整RabbitMQ配置参数:
  • 根据实际情况调整RabbitMQ的内存限制、连接数、队列长度等配置参数,以提高其性能和稳定性。
  • 例如,可以增大RabbitMQ的内存限制,调整消息的预取数量等。
  1. 增加RabbitMQ节点:
  • 如果单个RabbitMQ节点的处理能力已经达到瓶颈,可以考虑增加更多的RabbitMQ节点,使用集群的方式来处理消息。
  • 集群可以分散负载,提高消息的处理能力,并且可以提供高可用性和容错性。

三、优化消息生产和消费逻辑

  1. 优化消息生产逻辑:
  • 确保生产者发送消息的速度与消费者的处理能力相匹配,避免消息过快地堆积在队列中。
  • 可以考虑实施流量控制策略,限制生产者的发送速度。
  1. 优化消息消费逻辑:
  • 确保消费者能够及时处理接收到的消息,避免消息在消费者端积压。
  • 如果消费者处理消息时出现异常或错误,应确保能够及时处理并重新入队或进行其他处理。

四、使用消息持久化和监控报警

  1. 消息持久化:
  • 将消息设置为持久化,确保消息在RabbitMQ宕机或重启后不会丢失。
  • 这可以保护消息的安全性,并减少因消息丢失而导致的重试和积压问题。
  1. 监控和报警:
  • 使用监控工具对RabbitMQ进行实时监控,关注队列长度、消费者数量、消息处理速度等关键指标。
  • 设置报警机制,当发现消息积压超过一定阈值时,及时发出报警通知相关人员进行处理。

五、考虑消息降级和限流

  1. 消息降级:
  • 在消息积压严重时,可以考虑对部分非关键消息进行降级处理。
  • 例如,将某些消息的优先级降低,或者将其暂时存储到另一个队列中等待后续处理。
  1. 限流:
  • 通过限流机制来降低生产者发送消息的速度,以减轻RabbitMQ的负担。
  • 这可以通过在生产者端设置发送速率的限制来实现。

结论

感谢各位朋友们能够看到结尾,找不到工作?某直聘已读不回?不妨看看这里超快回复,助力每一位程序员早日找到理想的工作

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

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

相关文章

【数据库系列】MySQL基础知识:深入理解DDL、DML与DQL操作

MySQL是一个开源的关系型数据库管理系统(RDBMS),广泛用于数据存储和管理。理解MySQL的基本操作至关重要,尤其是数据定义语言(DDL)、数据操作语言(DML)和数据查询语言(DQL…

PAT1085 Perfect Sequence(25)

//判断是否是连续的数 //判断是否只能第一个数是最小值 #include <cstdio> #include <algorithm> typedef long long ll; using namespace std; int n,p; const int maxn 100010; int arr[maxn];int binary(int l, int r, ll tgt){if(arr[n-1] < tgt) return n…

Shell 编程基础知识

为什么要学 Shell&#xff1f; 学一个东西&#xff0c;我们大部分情况都是往实用性方向着想。从工作角度来讲&#xff0c;学习 Shell 是为了提高我们自己工作效率&#xff0c;提高产出&#xff0c;让我们在更少的时间完成更多的事情。 很多人会说 Shell 编程属于运维方面的知…

深入浅出UART驱动开发与调试:从基础调试到虚拟驱动实现

往期内容 本专栏往期内容&#xff1a;Uart子系统 UART串口硬件介绍深入理解TTY体系&#xff1a;设备节点与驱动程序框架详解Linux串口应用编程&#xff1a;从UART到GPS模块及字符设备驱动 解UART 子系统&#xff1a;Linux Kernel 4.9.88 中的核心结构体与设计详解IMX 平台UART驱…

Linux网络——IO模型和多路转接

通常所谓的IO&#xff0c;其本质就是等待通信和进行通信&#xff0c;即IO 等 拷贝。 那么想要做到高效的IO&#xff0c;就要在单位时间内&#xff0c;减少“等”的比重。 一.五种IO模型 阻塞 IO: 在内核将数据准备好之前, 系统调用会一直等待. 所有的套接字, 默认都是阻塞方…

VM Virutal Box的Ubuntu虚拟机与windows宿主机之间设置共享文件夹(自动挂载,永久有效)

本文参考如下链接 How to access a shared folder in VirtualBox? - Ask Ubuntu &#xff08;1&#xff09;安装增强功能&#xff08;Guest Additions&#xff09; 首先&#xff0c;在网上下载VBoxGuestAdditions光盘映像文件 下载地址&#xff1a;Index of http://…

AI的魔力:如何为开源软件注入智慧,开启无限可能

“AI的魔力&#xff1a;如何为开源软件注入智慧&#xff0c;开启无限可能” 引言&#xff1a; 在科技发展的浪潮中&#xff0c;开源软件生态一直扮演着推动创新与共享的重要角色。从Linux到Python&#xff0c;开源项目赋予了开发者全球协作的机会&#xff0c;推动了技术的飞速…

IThenticate 查重有无免费午餐?深度解析

经历过论文“折磨”的过来人&#xff0c;深知查重工具是写论文不可或缺的助手。而 iThenticate 查重系统&#xff0c;深受出版商、学术机构和研究人员喜爱。不过&#xff0c;每次看到它那昂贵的价格&#xff0c;就让很多小伙伴直呼&#xff0c;IThenticate查重系统就没有免费的…

启动SpringBoot

前言&#xff1a;大家好我是小帅&#xff0c;今天我们来学习SpringBoot 文章目录 1. 环境准备2. Maven2.1 什么是Maven2.2 创建⼀个Maven项⽬2.3 依赖管理2.3.1 依赖配置2.3.2 依赖传递2.3.4 依赖排除2.3.5 Maven Help插件&#xff08;plugin&#xff09; 2.4 Maven 仓库2.6 中…

DHCP服务(包含配置过程)

目录 一、 DHCP的定义 二、 使用DHCP的好处 三、 DHCP的分配方式 四、 DHCP的租约过程 1. 客户机请求IP 2. 服务器响应 3. 客户机选择IP 4. 服务器确定租约 5. 重新登录 6. 更新租约 五、 DHCP服务配置过程 一、 DHCP的定义 DHCP&#xff08;Dynamic Host Configur…

使用 Certbot 为 Nginx 自动配置 SSL 证书

1.安装Certbot和Nginx插件 sudo apt-get update sudo apt-get install certbot python3-certbot-nginx 2.获取和安装证书 运行Certbot自动安装SSL证书。注意替换 your_domain sudo certbot --nginx -d your_domain Certbot将自动与Lets Encrypt的服务器通信&#xff0c;验证域…

ros2键盘实现车辆: 简单的油门_刹车_挡位_前后左右移动控制

参考: ROS python 实现键盘控制 底盘移动 https://blog.csdn.net/u011326325/article/details/131609340游戏手柄控制 1.背景与需求 1.之前实现过 键盘控制 底盘移动的程序, 底盘是线速度控制, 效果还不错. 2.新的底盘 只支持油门控制, 使用线速度控制问题比较多, 和底盘适配…

DICOM医学影像应用篇——窗宽窗位概念、原理及实现详解

目录 窗宽窗位调整&#xff08;Windowing&#xff09;在DICOM医学影像中的应用 窗宽窗位的基本概念 窗宽&#xff08;Window Width, WW&#xff09; 窗位&#xff08;Window Level, WL&#xff09; 窗宽窗位调整的基本原理 映射逻辑 数学公式 窗宽窗位调整的C实现 代码…

天锐绿盾加密软件与Ping32联合打造企业级安全保护系统,确保敏感数据防泄密与加密管理

随着信息技术的飞速发展&#xff0c;企业在日常经营过程中产生和处理的大量敏感数据&#xff0c;面临着越来越复杂的安全威胁。尤其是在金融、医疗、法律等领域&#xff0c;数据泄漏不仅会造成企业巨大的经济损失&#xff0c;还可能破坏企业的信誉和客户信任。因此&#xff0c;…

HarmonyOS:@Provide装饰器和@Consume装饰器:与后代组件双向同步

一、前言 Provide和Consume&#xff0c;应用于与后代组件的双向数据同步&#xff0c;应用于状态数据在多个层级之间传递的场景。不同于上文提到的父子组件之间通过命名参数机制传递&#xff0c;Provide和Consume摆脱参数传递机制的束缚&#xff0c;实现跨层级传递。 其中Provi…

【Spring MVC】如何运用应用分层思想实现简单图书管理系统前后端交互工作

前言 &#x1f31f;&#x1f31f;本期讲解关于SpringMVC的编程思想之应用分层~~~ &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; 你的点赞就是小编不断更新的最大动力 &#x1f386;那…

【Linux】项目自动化构建工具-make/Makefile

【Linux】项目自动化构建工具-make/Makefile make 和 makefile 的概念如何清理项目推导过程Linux第⼀个小程序−倒计时 &#x1f30f;个人博客主页&#xff1a;个人主页 make 和 makefile 的概念 make是一个命令工具&#xff0c;是一个解释makefile中指令的命令工具&#xf…

arcgis for js点击聚合要素查询其包含的所有要素

功能说明 上一篇讲了实现聚合效果, 但是点击聚合效果无法获取到该聚合点包含的所有点信息 这一篇是对如何实现该功能的案例 实现 各属性说明需要自行去官网查阅 官网案例 聚合API 没空说废话了, 加班到12点,得休息了, 直接运行代码看效果就行, 相关重点和注意事项都在代码注…

【计算机视觉】图像基本操作

1. 数字图像表示 一幅尺寸为MN的图像可以用矩阵表示&#xff0c;每个矩阵元素代表一个像素&#xff0c;元素的值代表这个位置图像的亮度&#xff1b;其中&#xff0c;彩色图像使用3维矩阵MN3表示&#xff1b;对于图像显示来说&#xff0c;一般使用无符号8位整数来表示图像亮度&…

javaweb-day03-前端零碎

1.Ajax &#xff08;1&#xff09;概述 &#xff08;2&#xff09;原生Ajax-繁琐&#xff0c;现已基本弃用 2.Ajax-Axios &#xff08;2&#xff09;案例 3.前端工程化 3.1 基础 3.2 vue项目 &#xff08;1&#xff09;项目目录结构 &#xff08;2&#xff09;主要开发…