【从零开始学习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: 1retry:enabled: true #开启超时重试机制initial-interval: 1000ms #失败后的初始等待时间multiplier: 1 #失败后下次等待时长倍数,下次等待时长= Initial - interval * multipliermax-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%5Ev100%5Epc_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只有在收到确认后才会从队列中移除消息。如果消费者在处理过程中失败,未确认的消息将重新入队,供其他消费者处理。

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

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

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

相关文章

Debian12 安装留档@Virtual Box

在学蜜罐系统的时候,T-Pot 需要Debian,于是安装Debian12 下载安装光盘 先去中科大下载了12的安装光盘,然后在VirtualBox中创建一个新虚拟机,将安装光盘挂载上。 安装光盘下载地址:https://mirrors.ustc.edu.cn/debi…

【NumPy】全面解析NumPy的bitwise_and函数:高效按位与操作指南

🧑 博主简介:阿里巴巴嵌入式技术专家,深耕嵌入式人工智能领域,具备多年的嵌入式硬件产品研发管理经验。 📒 博客介绍:分享嵌入式开发领域的相关知识、经验、思考和感悟,欢迎关注。提供嵌入式方向…

抖音小程序如何生成二维码

1.页面结构 <image src{{imgUrl}}></image>2.代码结构 onLoad(options) {if (options.param) {var qrCode 13246897451257 //传入生成二维码的字符串this.generateQRCode(qrCode);}},//调起第三方库qrCodegenerateQRCode(text) {//调用了qrCode里面的apiconst api…

【静态分析】在springboot使用太阿(Tai-e)02

参考&#xff1a;使用太阿&#xff08;Tai-e&#xff09;进行静态代码安全分析&#xff08;spring-boot篇二&#xff09; - 先知社区 本文章使用的被分析代码为GitHub - JoyChou93/java-sec-code: Java web common vulnerabilities and security code which is base on springb…

本地部署 MiniCPM-Llama3-V 2.5

本地部署 MiniCPM-Llama3-V 2.5 0. 引言1. 性能评估2. 典型示例3. 本地部署4. 运行 WebUI Demo5. vLLM 部署 0. 引言 MiniCPM-Llama3-V 2.5 是 MiniCPM-V 系列的最新版本模型&#xff0c;基于 SigLip-400M 和 Llama3-8B-Instruct 构建&#xff0c;共 8B 参数量&#xff0c;相较…

Llama模型家族训练奖励模型Reward Model技术及代码实战(三) 使用 TRL 训练奖励模型

LlaMA 3 系列博客 基于 LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;一&#xff09; 基于 LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;二&#xff09; 基于 LlaMA 3 LangGraph 在windows本地部署大模型 &#xff08;三&#xff09; 基于 LlaMA…

闲话 .NET(3):.NET Framework 的缺点

前言 2016 年&#xff0c;微软正式推出 .NET Core 1.0&#xff0c;并在 2019 年全面停止 .NET Framework 的更新。 .NET Core 并不是 .NET Framework 的升级版&#xff0c;而是一个从头开始开发的全新平台&#xff0c;一个跟 .NET Framework 截然不同的开源技术框架。 微软为…

2024第三届AIGC开发者大会圆桌论坛:AI Agent中国落地发展现状及多模态结合具身智能的发展展望

在2024年第三届AIGC开发者大会上&#xff0c;多位业内专家齐聚一堂&#xff0c;共同探讨了AI Agent在中国的落地发展现状以及多模态结合具身智能的发展前景。本次圆桌论坛的嘉宾包括&#xff1a; Fast JP作者于金龙Agent创始人莫西莫必胜作者秦瑞January Agent创始人李晨 多模…

Android NDK系列(一)手动搭建Native Project

使用NDK编写的本地代码具有高性能等特性&#xff0c;在游戏、图形处理等领域有广泛应用&#xff0c;下面介绍如何手动搭建一个纯C版的Android项目&#xff0c;通过该项目可以理解Android的项目结构。 一、创建settings.gradle Android项目是基于Gradle构建的&#xff0c;首先得…

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

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

JVM1.8分代的理论基础和简单测试

你好&#xff0c;我是 shengjk1&#xff0c;多年大厂经验&#xff0c;努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注&#xff01;你会有如下收益&#xff1a; 了解大厂经验拥有和大厂相匹配的技术等 希望看什么&#xff0c;评论或者私信告诉我&#xff01; 文章目录 一…

海外仓系统哪家好?闭坑指南,擦亮眼睛选对系统

可以说现在的海外仓系统市场还是比较杂乱的&#xff0c;各种不同类型&#xff0c;不同收费标准的系统比比皆是&#xff0c;这让很多想引进海外仓系统的企业不知所措&#xff0c;不知道怎么选。 今天就聊一下在选择海外仓系统的时候应该如何考量&#xff0c;才能避免被坑&#…

C++之对象的使用

1、static成员 2、static成员优点 2、static成员函数 静态成员函数不能访问非静态成员原因&#xff1a;因为没有this指针。也不可以访问非静态成员函数。 可以通过对象来访问静态成员&#xff0c;但是不推荐这么使用&#xff0c;会让人误解成这个x_是属于对象的&#xff0c;但…

PyCharm基本配置内容

如何更换 Python 解释器 输入一段代码点击运行后&#xff0c;画面下方有一个路径如图中框中所示&#xff1a; 上面的路径为虚拟路径&#xff0c;可以改为我们自己设置的路径 点击设置&#xff0c;选择settings 选择Project&#xff1a;y002———》Python Interpreter&#…

python爬虫之pandas库——数据清洗

安装pandas库 pip install pandas pandas库操作文件 已知在本地桌面有一名为Python开发岗位的csv文件(如果是excel文件可以做简单修改即可&#xff0c;道理是通用的) 打开文件&#xff1a; 打开文件并查看文件内容 from pandas import DataFrame import pandas as pd data_c…

【自动驾驶技术栈学习】2-软件《大话自动驾驶》| 综述要点总结 by.Akaxi

----------------------------------------------------------------------------------------------------------------- 致谢&#xff1a;感谢十一号线人老师的《大话自动驾驶》书籍&#xff0c;收获颇丰 链接&#xff1a;大话自动驾驶 (豆瓣) (douban.com) -------------…

nuxt3+Element Plus项目搭建过程记录

背景 本文只记录项目搭建过程中遇到的一些问题和关键点&#xff0c;nuxt框架的说明和API请参照官网学习 官网&#xff1a;https://nuxt.com/docs/getting-started/introduction 1. 初始化项目 指令如下: npx nuxilatest init <project-name>我在安装过程中出现报错&a…

本地源码方式部署启动MaxKB知识库问答系统,一篇文章搞定!

MaxKB 是一款基于 LLM 大语言模型的知识库问答系统。MaxKB Max Knowledge Base&#xff0c;旨在成为企业的最强大脑。 开箱即用&#xff1a;支持直接上传文档、自动爬取在线文档&#xff0c;支持文本自动拆分、向量化、RAG&#xff08;检索增强生成&#xff09;&#xff0c;智…

AI视频智能分析技术赋能营业厅:智慧化管理与效率新突破

一、方案背景 随着信息技术的快速发展&#xff0c;图像和视频分析技术已广泛应用于各行各业&#xff0c;特别是在营业厅场景中&#xff0c;该技术能够有效提升服务质量、优化客户体验&#xff0c;并提高安全保障水平。TSINGSEE青犀智慧营业厅视频管理方案旨在探讨视频监控和视…

七人拼购新模式:革新购物体验,共创价值

在数字时代&#xff0c;消费者的购物体验正经历着前所未有的变革。七人拼购模式作为一种新兴的购物方式&#xff0c;通过汇集消费者的力量&#xff0c;实现商品价格的最优化&#xff0c;让消费者享受到前所未有的实惠与便利。以下&#xff0c;我们将以一款标价499元的商品为例&…