RabbitMq 消息可靠性问题(一) --- publisher发送时丢失
前言
消息从生产者发送到exchange, 再到 queue, 再到消费者。这个过程中有哪些有消息丢失的可能性呢?
- 发送时丢失:
- 生产者发送的消息未送达 exchange
- 消息到达 exchange 后未到达 queue
- MQ 宕机,queue将消息丢失
- consumer 接收到消息后未消费就宕机

消息可靠性问题及其对应的解决方案:
| 场景 | publisher发送时丢失 | MQ消息丢失 | consumer消费问题 |
|---|---|---|---|
| 解决方案 | 生产者确认机制 | 消息持久化 | 消费者消息确认&&失败重试机制 |
下面我们先说一下publisher 发送时丢失的问题应该如何处理
生产者确认机制的理论说明
RabbitMQ 提供了 publisher confirm 机制来避免消息发送到MQ过程中丢失。消息发送到MQ以后, 会返回一个结果给发送者,表示消息是否处理成功。结果有两种请求:
- publish-confirm, 发送者确认
- 消息成功投递到交换机,返回ack
- 消息未投递到交换机,返回nack
- publish-return, 发送回执
- 消息投递到交换机,但是没有路由到队列,返回ACK, 及路由失败原因
注意: 确认机制发送消息时, 需要给每个消息设置一个全局唯一 id, 以区分不同消息,避免ack 冲突

代码实现
下面基于SpringAMQP 实现的生产者确认机制
- 在 publisher 服务的 application,yml 中添加以下配置:
spring:rabbitmq:publisher-confirm-type: correlated # 开启异步回调publisher-returns: truetemplate:mandatory: true
配置说明:
- publish-confirm-type: 开启 publisher-confirm, 这里支持两种类型:
- simple: 同步等待 confirm 结果, 直到超时
- correlated: 异步回调, 定义ConfirmCallback, MQ 返回结果时会回调这个ConfirmCallback
- publish-returns: 开启 publish-return 功能,同样是基于 callback 机制,不过是定义 ReturnCallbcak
- template.mandatory: 定义消息路由失败时的策略。true, 则调用ReturnCallback, false: 则直接丢弃消息
ConfirmCallBack是基于每条消息设置的,所以需要一个全局唯一id 进行区分。
ReturenCallbcak 则是基于每个RabbitTemplate操作实例,是一种全局性的回调。
- 由于每个 RabbitTemplate 只能配置一个 ReturnCallback, 因此需要在项目启动过程中配置:
(这里可以实现ApplicationContextAware,它可以在SpringIOC 容器初始化的时候,进行一些全局性回调的操作)
@Slf4j
@Configuration
public class CommonConfig implements ApplicationContextAware {@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {// 获取 RabbitTemplate对象RabbitTemplate rabbitTemplate = applicationContext.getBean(RabbitTemplate.class);// 配置 ReturnCallbackrabbitTemplate.setReturnCallback((message, replayCode, replayText,exchange, routingKey) -> {// 记录日志log.error("消息发送到队列失败, 响应码:{}, 失败原因:{},交换机:{}, 路由key:{},消息:{},",replayCode, replayText, exchange, routingKey, message.toString());// 如果有需要的话,重发消息});}}
}
- 为每条发送的消息,指定消息 ID, 并编写对应的 ConfirmCallback
public void testSendMessage2SimpleQueue() throws InterruptedException {// 1. 准备消息String message = "hello, spring amqp!";// 2. 准备CorrelationData// 2.1 消息idCorrelationData correlationData = newCorrelationData(UUID.randomUUID().toString());// 2.2 准备 ConfirmCallbackcorrelationData.getFuture().addCallback(confirm -> {// 判断结果if(confirm.isAck()){// ACKlog.debug("消息成功投递到交换机!消息ID:{}",correlationData.getId());}else {// NACKlog.error("消息投递到交换机失败!消息ID:{}", correlationData.getId());// 重发消息}}, throwable -> {// 记录日志log.error("消息发送失败", throwable);// 重发消息});// 3.发送消息rabbitTemplate.convertAndSend("amq.topic", "asimple.test", message, correlationData);
}
总结
SpringAMQP 中处理消息确认的几种情况:
- publisher-confirm:
- 消息发送到 exchange, 返回 ack
- 消息发送失败,没有到达交换机,返回 nack
- 消息发送过程中出现异常,没有收到回执
- 消息成功发送到 exchange, 但没有路由到 queue, 调用 ReturnCallback
相关文章:
RabbitMq 消息可靠性问题(一) --- publisher发送时丢失
前言 消息从生产者发送到exchange, 再到 queue, 再到消费者。这个过程中有哪些有消息丢失的可能性呢? 发送时丢失: 生产者发送的消息未送达 exchange消息到达 exchange 后未到达 queue MQ 宕机,queue将消息丢失consumer 接收到消息后未消费…...
Java初识泛型
目录 一、包装类 1、基本数据类型和对应的包装类 2、装箱和拆箱 3、自动装箱和自动拆箱 二、什么是泛型 三、引出泛型 1、泛型的语法 四、泛型类的使用 1、语法 2、示例 3、类型推导(Type Inference) 六、泛型如何编译的 1、擦除机制 2、为什么不能实例化泛型类…...
寸照换底色技巧大全,超详细图文教程
在日常的设计工作中,我们常常需要将图片的背景色进行修改,以适应不同的场景和需求。其中最常用的方法就是寸照换底色技巧。本文将为大家介绍一些常见的寸照换底色技巧,并提供超详细的图文教程,帮助大家轻松完成这项任务。 一、使…...
这篇文章价值很大:股票历史分时成交数据怎么简单获取?【干货】
文章目录前言一、准备二、使用步骤1.引入库2,使用这个API查询历史分时数据:3.查询完整历史分时数据4.其他查询方法参数格式:[(市场代码, 股票代码), ...]参数:市场代码, 股票代码, 文件名, 起始位置, 数量参数:市场代码…...
muduo源码剖析--Buffer
Buffer类 Buffer类是自定义处理数据输入缓冲的类,底层是vector< char >,通过readIdx和writeIdx将缓冲区分为3个部分,第一部分是预留的8字节已经读出的缓冲区字节数、第二部分是还未读出的部分、第三部分是可写的部分。 Buffer类的设计…...
AI人工智能简介和其定义
全称:人工智能(Artificial Intelligence) 缩写:AI / ai 人工智能研究 亦称智械、机器智能,指由人制造出来的可以表现出智能的机器。通常人工智能是指通过普通计算机程序来呈现人类智能的技术。该词也指出研究这样的智…...
python数据清洗
数据清洗包括:空值,异常值,重复值,类型转换和数据整合这里数据清洗需要用到的库是pandas库,下载方式还是在终端运行 : pip install pandas.首先我们需要对数据进行读取import pandas as pddata pd.read_cs…...
Python3 os.makedirs() 方法、Python3 os.read() 方法
Python3 os.makedirs() 方法 概述 os.makedirs() 方法用于递归创建目录。像 mkdir(), 但创建的所有intermediate-level文件夹需要包含子目录。 语法 makedirs()方法语法格式如下: os.makedirs(path, mode0o777)参数 path -- 需要递归创建的目录。 mode -- 权限…...
【Linux安装数据库】Ubuntu安装mysql并连接navicat
Linux系统部署Django项目 文章目录Linux系统部署Django项目一、mysql安装二、mysql配置文件三、新建数据库和用户四、nivacat链接mysql一、mysql安装 linux安装mysql数据库有很多教程,根据安装方式不同,相关的步骤也不同。可以参考:【Linux安…...
GaussDB工作级开发者认证—第一章GaussDB数据库介绍
一. GaussDB概述 GaussDB是华为基于openGauss自研生态推出的企业级分布式关系型数据库。具备企业级复杂事物混合负载能力,同时支持分布式事务强一致性,同城跨AZ部署,数据0丢失,支持1000的计算节点扩展能力,4PB海量存储…...
阿里张勇:所有行业都值得用大模型重新做一遍!
数据智能产业创新服务媒体——聚焦数智 改变商业“2023阿里云峰会”于4月11日在北京国际会议中心隆重召开,本次峰会以" 与实俱进 为创新提速!"为主题,阿里巴巴集团董事会主席兼首席执行官张勇、阿里云智能集团首席技术官周靖人、…...
ES6(字符串的扩展与新增方法)
字符串的扩展与新增方法 1. 模板字符串 模板字符串解决了之前的字符串拼接 ESC下那个键:反引号()包裹>替换引号 ${变量名/表达式/函数}>替换引引加加导致的代码冗余 //ES5(引引加加) $(#result).append(There are <b> basket.c…...
rk3568点亮LCD(lvds)
rk3568 Android11/12 适配 lvds 屏 LVDS(Low Voltage Differential Signal)即低电压差分信号。1994年由美国国家半导体(NS)公司为克服以TTL电平方式传输宽带高码率数据时功耗大、电磁干扰大等缺点而研制的一种数字视频信号传输方…...
全终端办公电子邮件集成方案
面临挑战 应用场景复杂,经常需要在不同终端进行切换,多屏、跨屏及移动办公要求高; 业务系统较多,需要同时支持多种业务的开展,对第三方应用集成及协同办公要求高; 对邮件系统的稳定及高效性要求高&#x…...
再不转型为ChatGPT程序员,有遭受降维打击的危险
Open AI在演示GPT-4的时候,有这么一个场景:给一个界面草图,就可以生成网页代码。这个演示非常简单,如果界面原型比较复杂呢?像这样:ChatGPT能不能直接生成HTML, CSS,JavaScript代码,把这个网页给…...
maven使用教程
文章目录IDEA创建maven项目maven项目必有得目录结构项目构建关键字cleanvalidatecompiletestpackageverifyinstallsitedeploy命令使用方法方法一 在terminal终端执行方法二 在右侧得maven中双击依赖管理在pom.xml下 导包、scope的传递范围、打包方式依赖冲突声明优先原则就近原…...
Emlog底部显示当前在线人数
第一步:在模板文件里面创建“visitor.php”的文件吧下面代码入进去 code <?php//首先你要有读写文件的权限,首次访问肯不显示,正常情况刷新即可$online_log "slzxrs.dat"; //保存人数的文件到根目录,$timeout 30;//30秒内没…...
【java踩坑搞起】MybatisPlus封装的mapper不支持 join,那咋办
众所周知,Mybatis Plus 封装的 mapper 不支持 join,如果需要支持就必须自己去实现。但是对于大部分的业务场景来说,都需要多表 join,要不然就没必要采用关系型数据库了。 直到前几天,偶然碰到了这么一款叫做mybatis-p…...
【创造者】——什么是数学
吉姆罗恩在不经意间这样说过,要么你主宰生活,要么你被生活主宰。这不禁令我深思. 既然如此, 康德说过一句著名的话,既然我已经踏上这条道路,那么,任何东西都不应妨碍我沿着这条路走下去。带着这句话, 我们还要更加慎重…...
ROS系列——错误syntax error near unexpected token `$‘do\r‘‘
ROS系列——错误syntax error near unexpected token $do\r说明解决方法问题原因解决1.终端运行2.本文使用的方法,适用于代码行数较少其他方法,本质就是替换3.重新运行脚本说明 在运行.sh脚本时,报错: syntax error near unexpec…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...
成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习) 一、Aspose.PDF 简介二、说明(⚠️仅供学习与研究使用)三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...
