【从零开始学习RabbitMQ | 第二篇】如何确保MQ的可靠性和消费者可靠性

目录

前言:

MQ可靠性: 

数据持久化:

Lazy Queue: 

消费者可靠性:

消费者确认机制:

消费失败处理:

MQ保证幂等性:

方法一:

总结:


 

前言:

在上一篇文章中,我们介绍了如何确保生产者的可靠性,确保消息一定可以到达MQ。

【从零开始学习RabbitMQ | 第一篇】如何确保生产者的可靠性-CSDN博客icon-default.png?t=N7T8https://liyuanxin.blog.csdn.net/article/details/139261125?spm=1001.2014.3001.5502

但是MQ自己也是会丢失消息的,比如MQ的突然宕机或者消息过多造成的阻塞,因此我们这篇文章来介绍一下如何确保MQ的可靠性和消费者可靠性

默认情况下,RabbitMQ会把接收到的消息保存在内存中来降低消息收发的延迟,但这样会导致两个问题:

  • 一旦MQ宕机,内存中的消息会丢失
  • 内存空间有限,当消费者故障或者处理过慢的时候,会导致消息的积压,引发阻塞。 

想要保证MQ的可靠性,主要依赖于两种方式:

  • 数据持久化
  • Lazy Queue 

MQ可靠性: 

数据持久化:

RabbitMQ实现持久化主要有三个部分:

  1. 持久化队列(Durable Queues): 持久化队列指的是队列本身被存储在磁盘上,这样即使RabbitMQ服务器重启,队列也不会丢失。要创建持久化队列,需要在声明队列时设置durable属性为true。持久化队列中的消息默认不是持久化的,需要单独设置每条消息为持久化。

  2. 持久化消息(Persistent Messages): 持久化消息意味着消息本身被存储在磁盘上,因此即使RabbitMQ服务器重启,消息也不会丢失。在发送消息时,需要设置消息的deliveryMode属性为2(即PERSISTENT),这样RabbitMQ就会将消息存储到磁盘上。

  3. 持久化交换机(Durable Exchanges): 持久化交换器与持久化队列类似,指的是交换器被存储在磁盘上,这样服务器重启后交换器依然存在。声明交换器时,也需要设置durable属性为true。持久化交换器确保了消息路由的结构在服务器重启后能够保留。

当我们把消息持久化到磁盘中的时候,就避免了消息挤压造成的阻塞。但是当我们把消息持久化到磁盘中的时候,这个时候是不能接收新的消息的。

Lazy Queue: 

因此实际上把消息持久化到磁盘中不是一个很好的解决方案,在RabbitMQ的3.6.0版本后,增加了Lazy  Queue这个概念。其实就是懒惰队列:

懒惰队列的特性如下:

  • 接收到消息后直接存入磁盘而不是内存(内存只保留最近的消息,默认2048条)。
  • 消费者要消费消息的时候才会从磁盘中读取并加载到内存中。
  • 支持数百万条的消息存储。

在3.12版本后,所有的队列都是Lazy Queue模式,无法更改。

消费者可靠性:

消费者确认机制:

 为了确认消费者是否成功处理消息,RabbitMQ提供了消费者确认机制(Consumer Acknowledgement)。当消费者处理消息的结束之后,将会向RabbitMQ发送一个回执,告知自己消息的处理状态 ,消费者一共可以向Rabbitmq回执三种处理状态,分别是:

  • ACK:成功处理消息,RabbitMQ从队列中删除该消息
  • NACK:消息处理失败,RabbitMQ再次投递消息
  • REJECT: 消息处理失败并拒绝该消息,RabbitMQ从队列中删除该消息

而消费者确认机制并不用我们手写,Spring AMQP已经为我们实现了消费者消息确认机制,并允许我们通过配置文件的形式选择ACK处理方式,有三种:

  • none:不处理,消息投递给消费者之后就会ack,消息会从MQ中删除,不安全
  • manual:手动模式。需要自己调用api发送ack或者reject。
  • auto:托管给Spring AMQP 利用 AOP实现消费者确认机制。当业务正常执行的时候返回ack

当业务异常的时候,根据异常不同返回不同的结果:

  1. 如果是业务异常,自动返回nack
  2. 如果是消息处理或者校验异常,自动返回reject

Spring AMQP的消费者确认机制默认开启auto。

消费失败处理:

如果我们把消费者确认机制配置为auto的时候,当消费者出现异常之后,消息会不断的重新入队到队列,再重新发送给消费者。同样的消息再次引发异常,再次入队,再次发送给消费者。

这样会导致MQ的消息处理数量飙升,带来不必要的压力,因此除了把处理失败的消息重新进行处理之外,我们还应该有其他的处理方案。

我们可以利用Spring 的retry机制,在消费者出现异常的时候使用本地重试,而不是无限制的requeue到MQ队列中。

    listener:
      simple:
        prefetch: 1
        retry:
          enabled: true #开启超时重试机制
          initial-interval: 1000ms #失败后的初始等待时间
          multiplier: 1 #失败后下次等待时长倍数,下次等待时长= Initial - interval * multiplier
          max-attempts: 3 #最大重试次数
          stateless: true #true无状态,false有状态,如果业务中包含事务,就改为fasle

当我们开启重试模式之后,如果重试次数耗尽并且消息依然失败,那么就需要有MessageRecoverer接口来处理,这个接口包含三种不同的实现:

  • RejectAndDontRequeueRecoverer :重试耗尽之后,直接reject,丢弃消息。
  • ImmedIateRequeueMessageRecoverer : 重试耗尽之后,返回nack,消息重新入队
  • RepublishMessageRecoerer:重试耗尽之后,将失败消息投递到指定的交换机

如果消息丢失不会对业务产生重大影响,可以选择RejectAndDontRequeueRecoverer

如果希望消息有机会被重新处理,可以选择ImmediateRequeueMessageRecoverer

RepublishMessageRecoverer则适用于需要对失败消息进行进一步分析或记录的情况。

MQ保证幂等性:

通过上述的各种保证措施,我们基本上可以确保业务至少被执行一次。那对于一些需要保证幂等性的业务,我们要如何保证这个消息只被消费一次呢?

【从零开始学习重要知识点 | 第一篇】快速了解什么是幂等性以及常见解决方案_幂等性问题如何解决分布式锁-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/fckbb/article/details/136331113?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171689607216777224421340%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=171689607216777224421340&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-1-136331113-null-null.142^v100^pc_search_result_base1&utm_term=%E5%B9%82%E7%AD%89%E6%80%A7%20%E6%88%91%E6%98%AF%E4%B8%80%E7%9B%98%E7%89%9B%E8%82%89&spm=1018.2226.3001.4187

方法一:

给每一个消息都设置一个唯一ID,用ID区分是否被消费过。当我们消费一个消息的时候,先在数据库中查询是否存在这个数据的ID,如果不存在就消费。如果存在就说明这个消息之前被消费过。

其实他和我们上面黏贴的文章中介绍的token机制的思想很像。而在MQ中也不需要我们手动去设置唯一ID,可以在消费者的消息转换器中开启:

 我们可以看一看这个setCreateMessageIds这个方法中是如何构造id的:

这里逻辑就很清晰了,实际上就是在发消息的时候做一个if判断,如果我们设置了构造id,并且当前消息配置类的id为空,我们就为这个消息构造一个id。

 但是这种方法也有自己的缺点,也就是对业务逻辑有侵入性,而且还有额外的数据库操作

总结:

        在本文中,我们探讨了RabbitMQ作为领先的开源消息代理,如何通过一系列高级特性和策略来确保消息队列和消费者的高度可靠性。

首先,我们讨论了RabbitMQ的持久化机制,它允许消息和队列在服务器重启后依然保持不变。通过将消息标记为持久化,并在队列上启用持久化选项,我们可以确保关键数据不会因系统故障而丢失。

最后,我们介绍了消息确认机制,这是确保消息被成功处理的关键。消费者在处理完消息后发送确认回执,RabbitMQ只有在收到确认后才会从队列中移除消息。如果消费者在处理过程中失败,未确认的消息将重新入队,供其他消费者处理。

如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

以梦为马,不负韶华(3)-AGI在企业服务的应用

AGI在企业服务中,各应⽤已覆盖企业全流程,包含⼈⼒、法务、财税、流程⾃动化、知识管理和软件开发各领域。 由于⼤语⾔模型对⽂本处理类场景有着天然且直接的适配性,⽂本总结、⽂本内容⽣成、服务指引等发展起步早且应⽤成熟度更⾼。 在数据…

Captura完全免费的电脑录屏软件

一、简介 1、Captura 是一款免费开源的电脑录屏软件,允许用户捕捉电脑屏幕上的任意区域、窗口、甚至是全屏画面,并将这些画面录制为视频文件。这款软件具有多种功能,例如可以设置是否显示鼠标、记录鼠标点击、键盘按键、计时器以及声音等。此…

LeetCode题练习与总结:有序链表转换二叉搜索树--109

一、题目描述 给定一个单链表的头节点 head ,其中的元素 按升序排序 ,将其转换为平衡二叉搜索树。 示例 1: 输入: head [-10,-3,0,5,9] 输出: [0,-3,9,-10,null,5] 解释: 一个可能的答案是[0,-3,9,-10,null,5],它表…

医疗图像处理2023:Transformers in medical imaging: A survey

医学成像中的transformer:综述 目录 一、介绍 贡献与安排 二、CNN和Transformer 1.CNN 2.ViT 三、Transformer应用于各个领域 1.图像分割 1)器官特异性 ①2D ②3D 2)多器官类别 ①纯transformer ②混合架构 单尺度 多尺度 3)…

Kubernetes——监听机制与调度约束

目录 前言 一、监听机制 1.Pod启动创建过程 2.调度过程 1.指定调度节点 1.1强制匹配 1.2强制约束 二、硬策略和软策略 1.键值运算关系 1.硬策略——requiredDuringSchedulingIgnoredDuringExecution 2.软策略——preferredDuringSchedulingIgnoredDuringExecution …

Varjo XR-4功能详解:由凝视驱动的XR自动对焦相机系统

Varjo是XR市场中拥有领先技术的虚拟现实设备供应商,其将可变焦距摄像机直通系统带入到虚拟和混合现实场景中。在本篇文章中,Varjo的技术工程师维尔蒂莫宁详细介绍了这项在Varjo XR-4焦点版中投入应用的技术。 对可变焦距光学系统的需求 目前所有其他XR头…

基于STM32实现智能饮水机控制系统

目录 引言环境准备智能饮水机控制系统基础代码示例:实现智能饮水机控制系统 温度传感器数据读取水泵和加热器控制水位传感器数据读取用户界面与显示应用场景:家庭和办公室的智能饮水管理问题解决方案与优化收尾与总结 1. 引言 本教程将详细介绍如何在S…

自适应感兴趣区域的级联多尺度残差注意力CNN用于自动脑肿瘤分割| 文献速递-深度学习肿瘤自动分割

Title 题目 Cascade multiscale residual attention CNNs with adaptive ROI for automatic brain tumor segmentation 自适应感兴趣区域的级联多尺度残差注意力CNN用于自动脑肿瘤分割 01 文献速递介绍 脑肿瘤是大脑细胞异常和不受控制的增长,被认为是神经系统…

第二证券炒股知识:股票破发后怎么办?

当一只新股的价格跌破其发行价时,往往会受到商场出资者的关注。关于股票破发后怎么办,第二证券下面就为我们具体介绍一下。 股票破发是指股票的商场价格低于其发行价格或最近一次增发价格,股票破发往往是由于多种要素共同作用的结果&#xf…

强化学习——学习笔记2

在上一篇文章中对强化学习进行了基本的概述,在此篇文章中将继续深入强化学习的相关知识。 一、什么是DP、MC、TD? 动态规划法(DP):动态规划法离不开一个关键词,拆分 ,就是把求解的问题分解成若…

亡羊补牢,一文讲清各种场景下GIT如何回退

系列文章目录 手把手教你安装Git,萌新迈向专业的必备一步 GIT命令只会抄却不理解?看完原理才能事半功倍! 常用GIT命令详解,手把手让你登堂入室 GIT实战篇,教你如何使用GIT可视化工具 GIT使用需知,哪些操作…

Meta 推出新型多模态 AI 模型“变色龙”(Chameleon),挑战 GPT-4o,引领多模态革命

在人工智能领域,Meta 近日发布了一款名为“变色龙”(Chameleon)的新型多模态 AI 模型,旨在挑战 OpenAI 的 GPT-4o,并刷新了当前的技术标准(SOTA)。这款拥有 34B 参数的模型通过 10 万亿 token 的…

2-EMMC启动及各分区文件生成过程

EMMC的使用比nand flash还是复杂一些,有其特有的分区和电器性能 1、启动过程介绍 跟普通nand或spi flash不同,uboot前面还有好几级 在vendor某些厂商的设计中,ATF并不是BOOTROM加载后的第一个启动镜像,可能是这样的: …

微信小程序多端应用Donut Android生成签名

一、生成签名的作用 确保应用的完整性:签名可以确保应用在发布后没有被修改。如果应用被修改,签名就会改变,Android系统就会拒绝安装。确定应用的唯一身份:签名是应用的唯一标识,Android系统通过签名来区分不同的应用…

【Postman接口测试】第二节.Postman界面功能介绍(上)

文章目录 前言一、Postman前言介绍二、Postman界面导航说明三、使用Postman发送第一个请求四、Postman 基础功能介绍 4.1 常见类型的接口请求 4.1.1 查询参数的接口请求 4.1.2 表单类型的接口请求 4.1.3 上传文件的表单请求 4.1.4 JSON 类…

Linux软硬链接详解

软链接: ln -s file1 file2//file1为目标文件,file2为软链接文件 演示: 从上图可以得出: 软链接本质不是同一个文件,因为inode不同。 作用: 软连接就像是Windows里的快捷方式,里面存放的是目标…

动手学操作系统(三、通过IO接口直接控制显卡)

动手学操作系统(三、通过IO接口直接控制显卡) 在之前的学习内容中,我们成功编写了MBR主引导记录,在终端上进行了打印显示,在这一节我们使用MBR通过IO接口来直接控制显卡输出字符。 文章目录 动手学操作系统&#xff0…

5.28_Java语法_运算符,接收键盘数据

1、运算符 具体应用同我C语言操作符详解博客相同,另有补充会直接写 1.1、基本的算术运算符、符号做连接符 CSDN 具体应用同我C语言操作符详解博客相同 符号做连接符: ""符号与字符串运算连用的时候是用作连接符的,其结果依然是一个字符串…

“SSH服务器拒绝了密码,请再试一次”的问题解决思路

大家在使用XShell工具连接Ubuntu系统时,可能会出现错误如下: 通过在网上查阅资料和实践解决这个问题,将我的思路分享给大家! 首先,我会先从使用Xshell连接远程服务器会涉及哪些东西上思考这个问题,即通过ssh服务连接远…

【Python】 如何从日期中减去一天?

基本原理 在编程中,日期和时间的处理是一个常见的需求,尤其是在处理日志、调度任务、数据分析等场景中。Python 提供了多种方式来处理日期和时间,其中最常用的库是 datetime。datetime 模块包含了日期(date)、时间&am…