RabbitMQ 消息可靠性:怎么避免消息丢失

发布时间:2026/7/13 2:47:18
RabbitMQ 消息可靠性:怎么避免消息丢失 RabbitMQ 消息可靠性怎么避免消息丢失目录消息可能丢在哪生产者确认持久化消费者手动ACK死信队列幂等消费完整可靠性方案小结笔者主页文章《RabbitMQ 交换机四种交换机理解消息的路由规则》介绍了 RabbitMQ 的交换机和路由机制解决的是消息如何找到正确的队列。但消息成功发送出去并不代表一定能被可靠消费。生产环境中网络异常、服务宕机等情况都可能导致消息丢失。发了一条订单已支付的消息给库存系统库存系统没收到订单显示已支付库存没扣减。这种情况会导致订单状态和库存状态不一致是生产环境中需要重点避免的问题。消息从生产者到消费者中间经过的每一个环节都可能丢消息。要保证消息不丢需要覆盖整个链路。消息可能丢在哪消息的生命周期分三段每段都有丢失风险环节丢失原因后果生产者 → Broker网络抖动、Broker宕机消息根本没进队列Broker 存储队列和消息没做持久化Broker重启消息进过队列但重启后没了Broker → 消费者自动ACK模式下消费者拿到消息就崩溃消息被标记为已消费实际没处理生产者确认生产者把消息发给 Broker怎么知道 Broker 确实收到了默认情况下生产者发完就不管了Broker 有没有收到它不知道。网络抖一下消息就丢了生产者还觉得自己发成功了。RabbitMQ 提供了Publisher Confirm机制生产者发消息后Broker 会给一个确认回调告诉生产者我收到了或者出了问题。Spring Boot 里开启确认机制需要配置publisher-confirm-typespring:rabbitmq:publisher-confirm-type:correlatedpublisher-confirm-type有三个值值行为适用场景none不确认默认不关心消息是否到达Brokercorrelated异步回调每条消息单独确认生产环境推荐simple同步等待确认性能差仅调试用correlated模式下每条消息附带一个唯一 IDBroker 确认后通过回调函数通知生产者。如果 Broker 返回 nack拒绝说明消息没成功投递。生产环境中通常不会直接无限重试而是记录失败消息通过补偿任务或人工介入处理。ServicepublicclassReliableProducer{AutowiredprivateRabbitTemplaterabbitTemplate;PostConstructpublicvoidinitConfirmCallback(){// 确认回调rabbitTemplate.setConfirmCallback((correlationData,ack,cause)-{if(ack){System.out.println(消息到达Broker: correlationData.getId());}else{// 消息没到达Broker需要重试或记录System.err.println(消息投递失败: correlationData.getId(), 原因: cause);}});}publicvoidsendOrderMessage(StringorderId){// 消息唯一IDCorrelationDatacorrelationDatanewCorrelationData(orderId);rabbitTemplate.convertAndSend(order.exchange,order.pay,订单已支付: orderId,correlationData);}}注意Publisher Confirm 只保证消息到达了 Broker 的交换机不保证消息进了队列。如果 routing key 写错了消息到了交换机但没匹配到任何队列confirm 回调依然会返回 ack因为交换机收到了但消息被丢弃了。要确认消息是否进了队列还需要额外设置mandatory参数和ReturnsCallbackPostConstructpublicvoidinitReturnCallback(){// 消息无法路由到队列时触发回调rabbitTemplate.setReturnsCallback(returned-{System.err.println(消息被退回: returned.getMessage(), 交换机: returned.getExchange(), routingKey: returned.getRoutingKey(), 原因: returned.getReplyText());});}publicvoidsendOrderMessage(StringorderId){rabbitTemplate.setMandatory(true);// 消息无法路由时退回rabbitTemplate.convertAndSend(order.exchange,order.pay,订单已支付: orderId);}mandatory true告诉 Broker如果这条消息找不到匹配的队列不要默默丢掉退回来告诉我。持久化消息到了 Broker存在内存里。Broker 一重启内存清空消息全没了。要让消息扛住重启需要做持久化。持久化涉及三个对象三个都要设只设一个不够1. 交换机持久化声明交换机时设置durable trueBeanpublicDirectExchangeorderExchange(){// 持久化交换机returnnewDirectExchange(order.exchange,true,false);}2. 队列持久化声明队列时设置durable trueBeanpublicQueueorderQueue(){// 持久化队列returnnewQueue(order.queue,true);}3. 消息持久化发送消息时设置投递模式为持久化rabbitTemplate.convertAndSend(order.exchange,order.pay,message,msg-{// 持久化消息msg.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);returnmsg;});Spring AMQP 默认发送的消息就是持久化的但显式设置更稳妥。为什么三个都要设想一个场景队列设了持久化消息没设持久化。Broker 重启后队列恢复了但队列里的消息没了。反过来消息设了持久化队列没设持久化。Broker 重启后队列本身都没了消息往哪恢复持久化的代价是性能。每条消息都要写磁盘吞吐量会下降。如果业务场景允许少量丢失比如日志采集可以不做强持久化。但对于支付、订单这类关键业务持久化是底线。消费者手动ACK消费者从队列拿到消息后需要告诉 Broker “我处理完了”这个动作叫 ACKAcknowledgement。RabbitMQ 收到 ACK 后才会把消息从队列里删掉。问题在于Spring Boot 默认是自动 ACK。消费者一拿到消息RabbitMQ 就认为消费成功了立刻删除。如果消费者拿到消息后还没处理完就崩了消息已经从队列删了丢了。spring:rabbitmq:listener:simple:acknowledge-mode:manual# 改为手动确认手动 ACK 模式下消费者处理完消息后显式调用basicAck处理失败调用basicNackComponentpublicclassOrderConsumer{RabbitListener(queuesorder.queue)publicvoidhandleOrder(Messagemessage,Channelchannel)throwsIOException{// 拿到消息的投递标签用于ACKlongdeliveryTagmessage.getMessageProperties().getDeliveryTag();try{// 处理业务逻辑StringbodynewString(message.getBody());processOrder(body);// 处理成功确认消息// multiple false只确认这一条channel.basicAck(deliveryTag,false);}catch(Exceptione){// 处理失败拒绝消息// requeue false不重新入队交给死信队列处理channel.basicNack(deliveryTag,false,false);}}privatevoidprocessOrder(Stringbody){// 实际业务逻辑System.out.println(处理订单: body);}}basicNack的第三个参数requeue很关键requeue行为适用场景true消息重新放回队列头部下次还会被消费临时性错误比如数据库连接超时false消息不回队列如果有死信队列就进死信队列没有就被丢弃确定性错误比如消息格式不对设requeue true要小心如果消息本身有缺陷比如格式错误每次消费都失败每次都被放回队列然后又被消费又失败陷入死循环。这种情况应该设requeue false把消息扔进死信队列由人工或专门的消费者处理。死信队列消费失败的消息、过期没人消费的消息、队列满了溢出的消息这些消息不能直接丢掉得有个地方收容。这个地方叫死信队列Dead Letter QueueDLQ。消息变成死信有三种情况来源触发条件示例消费者拒绝basicNack 或 basicRejectrequeue false消息格式错误处理不了TTL 过期消息或队列设置了 TTL超时未被消费订单30分钟未支付超时消息队列满了队列达到最大长度新消息把旧消息挤出去队列设了 x-max-length声明死信队列和普通队列一样关键是在普通队列上绑定死信交换机ConfigurationpublicclassDlxConfig{// 死信交换机BeanpublicDirectExchangedlxExchange(){returnnewDirectExchange(dlx.exchange);}// 死信队列BeanpublicQueuedlxQueue(){returnnewQueue(dlx.queue,true);}// 死信绑定BeanpublicBindingdlxBinding(){returnBindingBuilder.bind(dlxQueue()).to(dlxExchange()).with(dlx.routing);}// 业务队列指定死信交换机BeanpublicQueueorderQueue(){MapString,ObjectargsnewHashMap();// 绑定死信交换机args.put(x-dead-letter-exchange,dlx.exchange);// 死信消息在死信交换机上的routing keyargs.put(x-dead-letter-routing-key,dlx.routing);returnnewQueue(order.queue,true,false,false,args);}}当order.queue里的消息被 reject 且 requeue false 时RabbitMQ 会自动把这条消息转发到dlx.exchange再路由到dlx.queue。你可以在死信队列上写一个消费者专门处理这些出了问题的消息记录日志、告警通知、人工排查。死信队列用于保存无法正常处理的消息方便后续排查和补偿。正常流程的消息走正常队列出了问题的消息走死信队列两套通道互不干扰。幂等消费前面的机制保证了消息大概率不丢但还有一个问题消息可能被重复投递。场景消费者拿到消息处理成功但在调basicAck之前网络断了。RabbitMQ 没收到 ACK认为消费失败把消息重新投递给另一个消费者。同一条消息被处理了两次。如果消费逻辑是扣库存扣两次就出事了。所以消费端需要做幂等处理同一个操作执行一次和执行多次结果相同。一种常见做法是使用消息唯一 ID 进行去重ComponentpublicclassIdempotentConsumer{AutowiredprivateRedisTemplateString,StringredisTemplate;RabbitListener(queuesorder.queue)publicvoidhandleOrder(Messagemessage,Channelchannel)throwsIOException{// 消息唯一IDStringmessageIdmessage.getMessageProperties().getMessageId();Stringkeyconsumed:messageId;// SETNX判断是否已消费过BooleanfirstTimeredisTemplate.opsForValue().setIfAbsent(key,1,24,TimeUnit.HOURS);if(Boolean.FALSE.equals(firstTime)){// 已经消费过了直接确认不做业务处理channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);return;}try{processOrder(newString(message.getBody()));channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);}catch(Exceptione){// 消费失败删除去重标记允许重试redisTemplate.delete(key);channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,false);}}}幂等消费的具体方案在之前的《接口幂等性》那篇里详细讲过这里不再展开。实现方式都是用唯一标识判断是否重复重复就跳过。完整可靠性方案把上面五个机制串起来一张图看完整的消息可靠性链路生产者 │ ├── 1. Publisher Confirm ──→ 确认消息到达Broker │ ▼ RabbitMQ Broker │ ├── 2. 交换机持久化 队列持久化 消息持久化 ──→ 重启不丢数据 │ ▼ 消费者 │ ├── 3. 手动ACK ──→ 处理完才确认崩溃了消息还在队列里 │ ├── 处理失败 ──→ basicNack(requeuefalse) ──→ 死信队列兜底 │ └── 4. 幂等消费 ──→ 重复投递不会重复处理机制解决哪个环节的丢失实现方式Publisher Confirm生产者 → BrokerBroker 收到后回调确认持久化Broker 存储交换机、队列、消息三者持久化手动 ACKBroker → 消费者处理完才确认否则消息保留死信队列消费失败的消息失败消息进死信队列等待处理幂等消费重复投递同一条消息只处理一次小结RabbitMQ 的可靠性需要从生产、存储、消费三个阶段分别处理。Confirm 解决生产端确认问题持久化保证 Broker 重启后的数据恢复手动 ACK 和幂等消费保证消费过程稳定死信队列为处理失败的消息提供兜底。但这套方案也有代价Publisher Confirm 多了一次网络往返持久化多了磁盘 IO手动 ACK 增加了消费端复杂度死信队列需要额外的监控和处理逻辑。可靠性越高吞吐量越低系统越复杂。如果你的场景是日志采集、行为埋点这种允许少量丢失的业务没必要上全套。但如果是支付、订单、库存这类关键业务这几个机制是最低配置。

相关新闻

别再瞎找山西省煤炭厅基本建设局网站了,老矿工都懂这其中的门道

别再瞎找山西省煤炭厅基本建设局网站了,老矿工都懂这其中的门道

咱山西人,提起煤炭,那感情是深到骨子里的。但你要问现在去哪个官网查最新的基建审批或者安全规范,十个人里有九个都得懵圈。为啥?因为机构改革那会儿,事儿分得比面条还细,原来的“山西省煤炭厅基本建设局”这牌子,早就随着大环境变了。很多人还在网上搜“山西省煤炭厅基…

发布时间:2026/7/13 2:46:15
江苏苏州建设行政主管部门网站:别只盯着首页,这些隐藏入口才是办事神器

江苏苏州建设行政主管部门网站:别只盯着首页,这些隐藏入口才是办事神器

说实话,每次打开那个所谓的“江苏苏州建设行政主管部门网站”,我心里都挺纠结的。一方面,它是咱们在苏州搞工程、办资质、查违规的唯一官方出口,躲是躲不掉的;另一方面,那界面设计,真的让人想摔键盘。我就纳闷了,都2024年了,为什么有些政务平台的体验还停留在十年前的…

发布时间:2026/7/13 2:45:36
建设环评备案登记网站怎么填?小白避坑指南,别等罚单来了才后悔

建设环评备案登记网站怎么填?小白避坑指南,别等罚单来了才后悔

搞建设怕麻烦?填表填到头秃?这篇手把手教你搞定建设环评备案登记网站,不花冤枉钱,不踩法律坑。说实话,刚接手这活儿的时候,我也懵圈。那时候我觉得,不就是填个表嘛,能有多难?结果呢,对着屏幕发呆俩小时,连“行业类别”都选不对。那种焦虑感,真不是吹的,心里直打鼓…

发布时间:2026/7/13 2:44:53
别被PPT骗了!会展行业门户网站建设,才是中小展商翻身的救命稻草

别被PPT骗了!会展行业门户网站建设,才是中小展商翻身的救命稻草

内容: 昨天半夜两点,我还在改方案。不是改PPT,是改我们那个“积灰”三年的官网。老板问我:这玩意儿还有人看吗?我说:有,而且很急。现在做会展,光靠线下发传单、扫楼,早就行不通了。客户还没见面,第一反应是搜你公司。搜不到?或者搜出来是个十年前风格的页面?那基本就…

发布时间:2026/7/13 3:55:55
济南源码网站建设:别被低价忽悠,这才是企业网站的真相

济南源码网站建设:别被低价忽悠,这才是企业网站的真相

上周在济南高新区,我和一位做传统制造业的老张喝茶。他手里攥着一份报价单,眉头紧锁。对方报价三千,包年维护,听起来很诱人。但老张心里没底,怕是个空壳子。这其实不是他一个人的困惑。很多济南老板在找济南源码网站建设时,都踩过类似的坑。他们以为网站就是个展示橱窗,…

发布时间:2026/7/13 3:54:55
Git 配置优先级与文件路径解析:3层配置覆盖规则与实战验证

Git 配置优先级与文件路径解析:3层配置覆盖规则与实战验证

Git 配置优先级与文件路径解析:3层配置覆盖规则与实战验证Git 作为现代软件开发中不可或缺的版本控制工具,其配置系统采用了独特的三层架构设计。理解这套配置体系的工作原理,能够帮助开发者精准控制不同环境下的行为表现,避免因配…

发布时间:2026/7/13 3:55:41
ipixel - 开源素材管理工具

ipixel - 开源素材管理工具

简介 iPixel 是一款专注于本地素材管理的桌面应用,为设计师、创作者和开发者提供高效、安全的数字资源管理解决方案。支持图片、音频、字体、3D模型等多种素材类型,数据本地存储,保护隐私安全。 图片预览 适用人群 设计师、艺术家、影音设计…

发布时间:2026/7/13 3:55:41
AD5593R与PIC32MX460F512L的混合信号处理方案

AD5593R与PIC32MX460F512L的混合信号处理方案

1. AD5593R与PIC32MX460F512L的硬件组合解析AD5593R这颗芯片最吸引人的地方在于它的多功能引脚配置——8个I/O引脚可以独立配置为12位DAC输出、12位ADC输入、数字输出或数字输入。在实际项目中,这种灵活性意味着我们可以用单颗芯片同时处理模数转换和数模转换任务&a…

发布时间:2026/7/13 3:55:41
别被坑了!济南网站建设公司 推荐行知科技,这几点真话得说透

别被坑了!济南网站建设公司 推荐行知科技,这几点真话得说透

做企业最怕啥? 不是没客户, 而是网站建完像鬼屋。打开速度慢, 手机端全乱码, 百度搜都搜不到。我见过太多老板, 花了几万块, 最后连个像样的页面都没有。其实, 找对团队比啥都强。今天不整虚的, 直接聊聊, 为啥我私底下总跟朋友提, 济南网站建设公司 推荐行知科技。先…

发布时间:2026/7/13 3:54:29
别瞎忙!贵州省住房和城乡建设厅网站报名网实操避坑指南

别瞎忙!贵州省住房和城乡建设厅网站报名网实操避坑指南

很多建筑人,一到报名季就慌。总觉得官网复杂,不敢点。其实,真没你想的那么难。只是细节太多,容易踩坑。我在这行干了八年。见过太多人因为一个小失误,白忙活一年。今天不整虚的。直接说点干货。先说最关键的:时间。很多人以为提前两天报名就行。大错特错。去年有个学员,…

发布时间:2026/7/13 0:00:05
北辰手机网站建设避坑指南:别被低价忽悠,这几点才是硬道理

北辰手机网站建设避坑指南:别被低价忽悠,这几点才是硬道理

说实话,刚入行那会儿,我也觉得做个手机网站跟玩似的。 找个模板,填填图,完事。 直到上个月,帮个北辰本地的老客户改网站,我才彻底醒过脑来。 那哥们儿之前为了省事儿,找了个几百块的“速成”网站。 结果呢?打开慢得像蜗牛,排版在手机上一塌糊涂。 客户投诉电话都快打爆…

发布时间:2026/7/13 0:00:37
网站建设怎么搭建服务器:新手避坑指南与真实成本拆解

网站建设怎么搭建服务器:新手避坑指南与真实成本拆解

这篇内容直接告诉你建站服务器怎么选、怎么配、怎么省钱,读完就能动手操作,不再被忽悠。别再去听那些云里雾里的技术术语,咱们只聊落地能用的干货。解决你从0到1搭建网站最头疼的硬件和配置问题。很多刚入行或者想自己折腾网站的朋友,一听到“搭建服务器”这几个字就头大。…

发布时间:2026/7/13 0:02:04
别装了,你的学院网站建设推进会就是场大型尴尬现场

别装了,你的学院网站建设推进会就是场大型尴尬现场

看着后台那点可怜的访问量,你急不急?方案改了八版,还是没人看。今天这文,只说怎么把会开成,把事做成。上周去隔壁职院蹭会,那场面,真叫一个窒息。会议室里坐满了人,领导在台上讲PPT,底下的人不是在玩手机,就是在发呆。投影仪闪了两下,灭了。没人去修,接着讲。这种会…

发布时间:2026/7/13 2:35:37
七彩建设集团官方网站怎么找?避坑指南与真实体验分享

七彩建设集团官方网站怎么找?避坑指南与真实体验分享

找官网找得头大?这篇直接告诉你怎么辨别真伪,别被假网站坑了钱。昨天半夜两点,我还在电脑前盯着屏幕,心里那个急啊。家里装修刚进场,工长突然说需要确认一份材料清单,说是七彩建设那边要求的。我手忙脚乱地打开浏览器,搜了一堆“七彩建设”,结果出来一堆广告,什么“七…

发布时间:2026/7/13 0:10:45
找可信赖的龙岗网站建设公司?别踩坑,看这几点就够

找可信赖的龙岗网站建设公司?别踩坑,看这几点就够

做企业,网站就是脸面。 在龙岗,想找个靠谱的网站公司,真不容易。 市面上广告满天飞。 承诺得天花乱坠。 最后交付的东西,却让人想砸电脑。 今天不聊虚的。 只聊怎么避坑。 怎么找到真正可信赖的龙岗网站建设团队。先说个大实话。 别信什么“三天上线”。 那是骗小白的。 正…

发布时间:2026/7/12 0:00:44
建站7年才悟出的网站建设思路,别再花冤枉钱了

建站7年才悟出的网站建设思路,别再花冤枉钱了

做建站这行整整7年了。 见过太多老板花几万块, 最后做出来的网站像个垃圾场。 今天不整那些虚头巴脑的术语。 就聊聊我踩过的坑, 和真正能落地的网站建设思路。很多老板一上来就问: “多少钱能做个高大上的?” 我通常直接劝退。 因为方向错了, 你给再多钱也是打水漂。 真正…

发布时间:2026/7/11 8:50:55
合肥的网站建设避坑指南:别被低价忽悠,这3个细节决定生死

合肥的网站建设避坑指南:别被低价忽悠,这3个细节决定生死

做企业官网最怕什么?不是技术难,是交钱后没人管,或者上线一个月连个访客都没有。这篇东西不扯虚的,直接告诉你怎么在合肥找个靠谱的团队,或者自己怎么避坑。先说个大实话,我在合肥混这行五年多,见过太多老板因为贪便宜吃大亏。你去百度搜“合肥的网站建设”,出来一堆报…

发布时间:2026/7/10 18:05:06
别被忽悠了!德州网站建设那些坑,我拿真金白银换来的教训

别被忽悠了!德州网站建设那些坑,我拿真金白银换来的教训

做这行久了,心里就憋着一股火。每次看到客户拿着网上抄来的模板,问我能不能做成“苹果官网”那种效果。我就想笑。真的,太想笑了。今天咱不整那些虚头巴脑的专业术语。就聊聊德州网站建设里,那些让人头秃的真实事儿。我有个客户,老张。他是做德州本地建材的,实在人。当初…

发布时间:2026/7/13 2:08:03