四种途径提高RabbitMQ传输数据的可靠性(二)

柯南君:看大数据时代下的IT架构(2)消息队列之RabbitMQ-基础概念详细介绍 柯南君上一章《柯南君:看大数据时代下的IT架构(1)业界消息队列对比 》中,粗略的讲了一下,目前消息队列的几种常见产品的优劣对比,接下来的几章节会分别详细阐述,本章介绍RabbitMQ,好吧,废话少说,正式开始: 一、基础概念详细介绍 1、引言 你是否遇到过两个(多个)系统间需要通过定时任务来同步某些数据?你是否在为异构系统的不同进程间相互调用、通讯的问题而苦恼、挣扎?如果是,那么恭喜你,消 阅读详情

三、生产者确认机制

针对问题(1),我们可以通过生产者的确认消息机制来解决,主要分为两种:第一是事务机制、第二是发送方确认机制

1、事务机制

与事务机制相关的有三种方法,分别是channel.txSelect设置当前信道为事务模式、channel.txCommit提交事务和channel.txRollback事务回滚。如果事务提交成功,则消息一定是到达了RabbitMQ中,如果事务提交之前由于发送异常或者其他原因,捕获后可以进行channel.txRollback回滚。

// 将信道设置为事务模式,开启事务
channel.txSelect(); 
// 发送持久化消息
channel.basicPublish(EXCHANGE_NAME, ROUTING_KEY, MessageProperties.PERSISTENT_TEXT_PLAIN, "transaction messages".getBytes()); 
// 事务提交
channel.txCommit();

发生异常之后事务回滚

如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。

try {
   channel.txSelect();
 channel.basicPublish(exchange, routingKey, MessageProperties.PERSISTENT_TEXT_PLAIN, "transaction messages".getBytes());
 channel.txCommit();
  } catch (Exception e){
 e.printStackTrace();
 channel.txRollback();
 }

2、确认机制

 生产者将信道设置为confirm确认模式,确认之后所有在信道上的消息将会被指派一个唯一的从1开始的ID,一旦消息被正确匹配到所有队列后,RabbitMQ就会发送一个确认Basic.Ack给生产者(包含消息的唯一ID),生产者便知晓消息是否正确到达目的地了。

 

四种途径提高RabbitMQ传输数据的可靠性(二)

 

消息如果是持久化的,那么确认消息会在消息写入磁盘之后发出。RabbitMQ中的deliveryTag包含了确认消息序号,还可以设置multiple参数,表示到这个序号之前的所有消息都已经得到处理。确认机制相对事务机制来说,相比较代码来说比较复杂,但会经常使用,主要有单条确认、批量确认、异步批量确认三种方式。

2.1 单条确认

此种方式比较简单,一般都是一条条的发送,代码如下:

try {
 Connection connection = connectionFactory.newConnection();
 Channel channel = connection.createChannel();
 //set channel publisher confirm mode 
 channel.confirmSelect();
 // publish message
 channel.basicPublish("exchange", "routingkey", null, "publisher confirm test".getBytes());
 if (!channel.waitForConfirms()) {
 // publisher confirm failed handle
 System.out.println("send message failed!");
 }
} catch (Exception e) {
 e.printStackTrace();
}

如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。

2.2 批量确认

问:批量确认comfirm需要解决出现返回的Basic.Nack或者超时情况的话,客户需要将这一批次消息全部重发,那么采用什么样的存储结构才能合适地将这些消息动态筛选出来。

最好是需要增加一个缓存,将发送成功并且确认Ack之后的消息去除,剩下Nack或者超时的消息,改进之后的代码如下:

// take ArrayList or BlockingQueue as a cache
List<Object> cache = new ArrayList<>();
// set channel publisher confirm mode
channel.confirmSelect();
for (int i=0; i < 20; i++) {
 // publish message
 String message = "publisher message["+ i +"]";
 cache.add(message);
 channel.basicPublish("exchange", "routingkey", null, message.getBytes());
 if (channel.waitForConfirms()) {
 // remove message publisher confirm
 cache.remove(i);
 }
 // TODO handle Nack message:republish
}
} catch (Exception e) {
  e.printStackTrace();
  // TODO handle Nack message:republish
}

2.3 异步批量确认

异步确认方式通过在客户端addConfirmListener增加ConfirmListener回调接口,包括handleAck与handleNack处理方法:

每次发送消息confirmSet集合元素加1,当消息被确认ack进入handleAck方法时,“unconfirm”集合中删除响应的一条(multiple设置为false时)或者多条记录(multiple设置为true时),其中存储缓存最好采用SortedSet数据结构

代码如下:

try {
 Connection connection = connectionFactory.newConnection();
 Channel channel = connection.createChannel();
 // take as a cache
 SortedSet cache = new TreeSet();
 // set channel publisher confirm mode
 channel.confirmSelect();
 for (int i = 0; i < 20; i++) {
 // publish message
 long nextSeqNo = channel.getNextPublishSeqNo();
 String message = "publisher message[" + i + "]";
 cache.add(message);
 channel.basicPublish("exchange", "routingkey", MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());
 cache.add(nextSeqNo);
 }
 // add confirmCalback: handleAck, handleNack
 channel.addConfirmListener(new ConfirmListener() {
 @Override
 public void handleAck(long deliveryTag, boolean multiple) {
 if (multiple) {
 // batch remove ack message
 cache.headSet(deliveryTag - 1).clear();
 } else {
 // remove ack message
 cache.remove(deliveryTag);
 }
 }
 @Override
 public void handleNack(long deliveryTag, boolean multiple) {
 // TODO handle Nack message:republish
 }
 });
} catch (Exception e) {
 e.printStackTrace();
 // TODO handle Nack message:republish
}

3、总结比较

1)是确认机制好呢?还是事务机制?两者可以共存吗?

确认机制相对于事务机制,最大的好处就是可以异步处理提高吞吐量,不需要额外等待消耗资源。但是两者时候不能同时共存的。

2)那么确认机制的三种方式之间呢?实际产生环境是推荐哪一种呢?(其实毫无疑问当然是推荐异步批量确认方式)

批量确认的最大问题就是在于返回的Nack消息需要重新发送,以上普通单条确认、批量确认、批量异步确认三种方法,在实际生产环境中强烈推荐使用批量异步确认方式。

四、消息与队列的持久化

针对的问题(2),我们可以通过增加队列与消息的持久化来实现。

1、交换器的持久化

交换器的持久化是通过声明队列durable参数为true实现的,如果交换器不设置持久化,那么在RabbitMQ服务器重启之后,相关的交换器元数据会丢失,消息不会丢失,只是不能将消息发送到这个交换器中。因此,都是建议将其置为持久化。

channel.exchangeDeclare(EXCHANGE_NAME, "direct", true, false, null);

2、队列的持久化

队列持久化同理与交换器持久化,只是RabbitMQ服务器重启之后,相关的元数据会丢失,数据也会跟着丢失,消息也自然丢失。

 channel.queueDeclare(QUEUE_NAME, true, false, false, null);

3、消息的持久化

队列的持久化不能保证内存存储的消息不会丢失,要确保消息不会丢失,需要将其通过设置BasicProperties中的deliveryMode属性为2可实现消息的持久化(PERSISTENT_TEXT_PLAIN实际上已经封装了这个属性),也就是说只有实现了队列与消息的持久化,才能保证消息不会丢失。

// 其中的2就是投递模式
public static Class final BasicProperties_PERSISTENT_TEXT_PLAIN = 
new BasicProperties("text/plain", null, null, 2, null, null, null, null, null, null, null, null, null);

4、消息丢失的几种情况

但实际上不是设置了交换器、队列、消息持久化就能一定保证消息不会被丢失,以下几种情况是可能丢失的,比如:

1)设置autoAck为true,消费者收到消息后,还没处理就宕机了,这样也算数据丢失,解决办法是设置为false,之后手动确认。

2)在设置了持久化后消息存入RabbitMQ之后,还需要一段时间才能存入磁盘之中(虽然很短,但不能忽视),RabbitMQ并不会为每条消息都今次那个同步存盘,可能只会保存到操作系统缓存之中而不是物理磁盘中,如果RabbitMQ这个时间段内宕机、异常、重启等情况,消息也会丢失,解决办法是引入RabbitMQ的镜像队列机制(类似于集群,Master挂了切换到Slave)

 

总结

没有完全十全十美的方式能保证数据能100%不丢失,并且最大效率节约性能消耗等,两篇博文虽然已经提出常用的四种方式,当实际环境中整个RabbitMQ环境在搭建没有结合实际的生产业务环境的话,也会发生消息丢失的等情况,解决这样的问题无非就完善消息备份,健全RabbitMQ集群..........

如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。

RabbitMQ教程(安装与使用详解,Spring集成) RabbitMQ教程,面试题。消息队列(MQ),本质是个队列,队列中存放的内容是message。MQ用于不同进程Process/线程Thread之间通信。本文介绍RabbitMQ的使用。RabbitMQ实战教程。 阅读详情

相关推荐

MOSFET热失效机理与保护电路设计:实战案例

深入解析MOSFET工作原理及其在高温下的失效机制,结合实际案例探讨有效保护电路设计,提升系统可靠性与安全性。

weixin_28713083的博客 852

【MQ】如何确保RabbitMQ消息可靠性传递?

正在学RabbitMQ,特此记录一下,这里就不讲RabbitMQ基础了,直接进入主题。 TODO:记录下具体的springboot中具体如何配置 mq:消息中间件(一)MQ详解及四大MQ比较 我们都知道,消息从生产端到消费端消费要经过3个步骤: 生产端发送消息到RabbitMQ; RabbitMQ发送消息到消费端; 消费端消费这条消息; 这3个步骤中的每一步都有可能导致消息丢失,消息丢失不可怕,可怕的是丢失了我们还不知道,所以要有一些措施来保证系统的可靠性。这里的可靠并不是一定就100%不丢失了,磁盘

fearless的博客 2972

BGE(BAAI General Embedding)模型详解

BGE(BAAI General Embedding)是北京智源人工智能研究院(BAAI)推出的通用文本嵌入模型系列,旨在为各种自然语言处理任务提供高质量的向量表示。

ttyy1112的专栏 7563

RabbitMQ(三)保证消息的可靠性传输【重要】

一、Rabbit如何保证消息的可靠性传输(如何处理消息丢失的问题)? 1、生产者弄丢了数据(事务、confirm) 生产者将数据发送到RabbitMQ的时候,可能数据就在半路给搞丢了,因为网络问题啥的,都有可能。 此时可以选择用RabbitMQ提供的事务功能,就是生产者发送数据之前开启RabbitMQ事务channel.txSelect,然后发送消息,如果消息没有成功被RabbitMQ接...

fox_bert的博客 1328

从零构建PEMFC仿真模型:MATLAB/Simulink中的模块化拆解与系统集成

本文详细介绍了如何在MATLAB/Simulink环境中从零构建质子交换膜燃料电池(PEMFC)仿真模型,包括电化学模型、气体供应系统和热管理系统的模块化实现。通过多物理场耦合技巧和系统集成策略,帮助工程师和研究者高效开发PEMFC控制策略,优化性能并实现实时仿真。

weixin_29294975的博客 362

变焦跟踪理论基础(如何在变焦过程中保持清晰)

如何在整个变焦过程中一直保持图像的清晰度或焦点是变焦跟踪的主要挑战。 当用户在缩放跟踪的情况下改变缩放时,设备保持对焦。 然而,在没有变焦跟踪的情况下,图像变得失焦,图像在变焦跟踪后由于自动对焦(AF)算法才最终对焦。...................................................

ChenYX的博客 20万+

消息队列专题(高级特性篇):RabbitMQ 如何保证消息的可靠性投递、传输和消费

我们使用 RabbitMQ 进行消息处理一般都需要保证消息的可靠性,而消息的可靠性又可以根据消息的不同处理阶段分为可靠性投递、传输和消费。 本篇博客将针对这三种情况介绍相应的设计方案,首先来看一下消息的可靠性投递。 消息的可靠性投递 1. 消息投递模式 消息可靠性投递,是指保证生产者能够把消息 100% 发送到消息队列中,生产者 Producer 为我们提供了两种消息投递模式:Confirm 确认模式 和 Return 退回模式 ,这两种模式是保障消息可靠性投递的核心,先来了解下这两种模式。 Confir

盛夏温暖流年 1570

彻底卸载Ubuntu双系统,并完美回收100G空间给D盘

本文记录了安全卸载Ubuntu双系统并回收磁盘空间的全过程。作者首先通过Windows命令行彻底清除Ubuntu启动项,避免GRUB引导报错;随后在磁盘管理中删除Linux分区,将100G未分配空间合并至相邻的D盘。针对C盘空间不足问题,作者采用Dism++清理系统文件,并将用户文档、聊天记录等迁移至扩容后的D盘。最终实现了引导纯净、空间合理分配的目标,特别强调分区扩展必须遵循"相邻原则",建议通过间接迁移而非直接扩容来优化系统盘空间管理。

2403_85993278的博客 1514

使用RabbitMQ传输大文件,保证其完整性

最近计划用RabbitMQ传输文件,对于容量超过1G的大文件,肯定需要对文件进行分块传输;如果某一块丢失了,或者有损坏,必须有一种机制,通知发送方重新发送。Direct和Topic模式都可以用。下面是我的研习和设计思路。RabbitMQ本身提供的确认机制RabbitMQ通过Publish Confirm和Consumer Acknowledgement机制,让发送方和接收方分别与broker产生确认

唐麦片的专栏 2万+

用长tree方式做等长线

1)写一个sdc,把等长线的起点设置成clock source,用于创建create_clock,至于period和waveform等参数随便写即可。然后clock_opt -from build_clock -to route_clock即可。3)在正式cts之前或之后,给自己创建的scenario长tree并don't touch。前面讲过了如何用set_data_check做等长线,这里再讲一下如何用cts的方式做。2)为该clock创建一个新mode,并创建对应的scenario。

m0_61544122的博客 623

Unity 面试篇⚠️ | Unity性能优化好,山寨机都能跑~

Unity 面试篇⚠️ | Unity性能优化好,山寨机都能跑~

m0_58523831的博客 1万+

四种途径提升RabbitMQ传输数据的可靠性

前言 RabbitMQ虽然有对队列及消息等的一些持久化设置,但其实光光只是这一个是不能够保障数据的可靠性的,下面我们提出这样的质疑: (1)RabbitMQ生产者是不知道自己发布的消息是否已经正确达到服务器呢,如果中间发生网络异常等情况呢?消息必然会丢失! (2)RabbitMQ如果没有设置队列持久化,RabbitMQ服务器重后队列的元数据会丢失,消息自然也会丢失! (3)Rabbit...

weixin_30885111的博客 123

CVAEGAN实现锂离子电池EIS数据增强:基于健康状态的阻抗谱生成

本文提出了一种基于CVAEGAN的锂离子电池EIS数据增强方法。该方法结合了变分自编码器和生成对抗网络的优点,能够根据指定的健康状态(SoH)生成高质量的EIS阻抗谱数据。文章详细介绍了数据预处理流程、模型架构设计(包括编码器、解码器和判别器),并提供了完整的PyTorch实现代码。通过条件生成的方式,该方法可以有效解决电池健康评估中标注数据不足的问题,为基于数据驱动的电池诊断提供更丰富的训练样本。实验结果表明,生成的EIS数据具有良好的真实性和多样性,可用于增强电池健康状态评估模型的性能。

huanghm88的专栏 501

mq集群要建传输队列吗_四种途径提升RabbitMQ传输数据的可靠性(二)

前言上一篇四种途径提高RabbitMQ传输消息数据的可靠性(一)已经介绍了两种方式提高数据可靠性传输的方法,这一篇继续针对上一篇中提出的问题(1)与问题(2)提出解决常用的方法,三、生产者确认机制针对问题(1),我们可以通过生产者的确认消息机制来解决,主要分为两种:第一是事务机制、第二是发送方确认机制1、事务机制与事务机制相关的有三种方法,分别是channel.txSelect设置当前信道为事务模...

weixin_39913807的博客 111

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Jmeter 测试 MQ 接口怎么做?跟我学秒变大神!

MQ(message queue)消息队列,是基础数据结构 先进先出 的一种典型数据结构。一般用来解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构。MQ 主要产品包括:RabbitMQ、ActiveMQ、RocketMQ、ZeroMQ、KafkaMQTT 是轻量的 (Lightweight)、发布订阅模式 (PubSub) 的物联网消息协议如果已经有 MQTT 环境,环境搭建这一章节,可以跳过。

2401_83396248的博客 1012

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

技术研发与产品迭代中的创新方法论:从痛点挖掘到方案验证

在技术研发和产品迭代中,系统性地寻找创新点并进行有效改进是一项核心能力。创新并非依赖灵感,而是基于一套可学习、可执行的方法论。其原理在于通过结构化框架,将模糊的“点子”转化为可定义、可衡量、可验证的技术问题。从技术价值看,这套方法论能显著提升研发效率,帮助工程师和产品经理突破性能瓶颈、优化用户体验并降低资源成本。在应用场景上,它广泛适用于算法优化、系统设计、功能增强以及学术研究中的论文开题。具体实践中,常从问题驱动和技术驱动两个维度切入:问题驱动聚焦于现有方案的性能瓶颈与用户体验缺陷,例如通过模型剪枝、知识

weixin_33850015的博客 432

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

AGI技术落地实战:从部署到集成的全流程指南

人工智能(AI)正从实验室走向产业应用,其核心驱动力在于模型能力的工程化落地。理解AI的工作原理,特别是大型语言模型(LLM)和多模态模型的推理机制,是技术价值实现的基础。这些技术通过模拟人类认知过程,处理文本、图像乃至视频信息,为自动化与内容创作带来了革命性潜力。在实际应用场景中,AGI(通用人工智能)的部署与集成成为关键。开发者需要掌握从环境搭建、模型选择到API集成的全链路实践,其中涉及GPU资源管理、提示词工程等具体技术环节。本文聚焦于AGI的可用性与落地性,通过拆解多模态AGI的核心能力与部署方案

weixin_34050519的博客 750

goalng开发_开发篇

Go 面试,基础知识

qq_46640341的博客 1161

计算机扫盲(下篇)

由于篇幅问题这篇文章被迫分成上下两篇建议反复上下对比着看,能应付生活中的使用就行。不是学操作系统的不用了解太深。实在不会就喂给ai帮你理解。逆向工程 = 通过分析程序的二进制文件,理解它的行为和逻辑。正常开发:源代码 → 编译 → 可执行文件 逆向工程:可执行文件 → 反汇编/反编译 → 理解逻辑5.2.1 指令与机器码1. 指令的组成 机器码格式(x86/x64):必会的汇编指令2. 常见寄存器3. 汇编代码中的栈重要观念:函数调用时生成的栈帧,在汇编层面根本不是一个必须存在的“结构”。, , , 等指

2504_94717629的博客 527

消息的传输控制拒绝和英达

消息的应答 RabbitMQ有两种应答模式,自动和手动。这也是AMQP协议所推荐的。这在point-to-point和broadcast都是一样的。 自动应答-当RabbitMQ把消息发送到接收端,接收端把消息出队列的时候就自动帮你发应答消息给服务。 手动应答-需要我们开发人员手动去调用ack方法去告诉服务已经收到。 文档推荐在大数据传输中,如果对个别消息的丢失不是很敏感的

石头视角 763

基于rabbitMQ实现在高并发下性能倍增

以服务与服务之间的调用来举个例子,比如我们提供的是rest服务,那么如果在高并发下访问rest服务究竟能支撑多大的并发量呢?

菜 头笔记 2万+

史上最透彻的 RabbitMQ 可靠消息传输实战

作者:极客慧链接:https://my.oschina.net/jikeh/blog/2207127可能是缓存架构之史上讲的最明白的 RabbitMQ 可靠消息传输实战演...

程序员之家 1484

Python操作rabbitmq 实践笔记

发布/订阅系统 1.基本用法 生产者 1 import pika 2 import sys 3 4 username = 'wt' #指定远程rabbitmq的用户名密码 5 pwd = '111111' 6 user_pwd = pika.PlainCredentials(username, pwd) 7 s_conn = pika.Blocking...

weixin_30765577的博客 470
上一篇: 四种途径提高RabbitMQ传输消息数据的可靠性(一)
下一篇: kafka 数据可靠性深度解读
javaQQ群 866865133
博客等级 码龄8年 59粉丝 309原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值