网易首页 > 网易号 > 正文 申请入驻

引入RabbitMQ后,你如何保证全链路数据100%不丢失?

0
分享至

  我们都知道,消息从生产端到消费端消费要经过3个步骤:

  生产端发送消息到RabbitMQ;

  RabbitMQ发送消息到消费端;

  消费端消费这条消息;

  这3个步骤中的每一步都有可能导致消息丢失,消息丢失不可怕,可怕的是丢失了我们还不知道,所以要有一些措施来保证系统的可靠性。这里的可靠并不是一定就100%不丢失了,磁盘损坏,机房爆炸等等都能导致数据丢失,当然这种都是极小概率发生,能做到99.999999%消息不丢失,就是可靠的了。下面来具体分析一下问题以及解决方案。

  生产端可靠性投递

  生产端可靠性投递,即生产端要确保将消息正确投递到RabbitMQ中。生产端投递的消息丢失的原因有很多,比如消息在网络传输的过程中发生网络故障消息丢失,或者消息投递到RabbitMQ时RabbitMQ挂了,那消息也可能丢失,而我们根本不知道发生了什么。针对以上情况,RabbitMQ本身提供了一些机制。

  事务消息机制

  事务消息机制由于会严重降低性能,所以一般不采用这种方法,我就不介绍了,而采用另一种轻量级的解决方案——confirm消息确认机制。

  confirm消息确认机制

  什么是confirm消息确认机制?顾名思义,就是生产端投递的消息一旦投递到RabbitMQ后,RabbitMQ就会发送一个确认消息给生产端,让生产端知道我已经收到消息了,否则这条消息就可能已经丢失了,需要生产端重新发送消息了。

  通过下面这句代码来开启确认模式:

  channel.confirmSelect();// 开启发送方确认模式

  然后异步监听确认和未确认的消息:

  channel.addConfirmListener(new ConfirmListener() {
//消息正确到达broker
@Override
public void handleAck(long deliveryTag, boolean multiple) throws IOException {
System.out.println("已收到消息");
//做一些其他处理
}

  //RabbitMQ因为自身内部错误导致消息丢失,就会发送一条nack消息
@Override
public void handleNack(long deliveryTag, boolean multiple) throws IOException {
System.out.println("未确认消息,标识:" + deliveryTag);
//做一些其他处理,比如消息重发等
}
});

  这样就可以让生产端感知到消息是否投递到RabbitMQ中了,当然这样还不够,稍后我会说一下极端情况。

  消息持久化

  那消息持久化呢?我们知道,RabbitMQ收到消息后将这个消息暂时存在了内存中,那这就会有个问题,如果RabbitMQ挂了,那重启后数据就丢失了,所以相关的数据应该持久化到硬盘中,这样就算RabbitMQ重启后也可以到硬盘中取数据恢复。那如何持久化呢?

  message消息到达RabbitMQ后先是到exchange交换机中,然后路由给queue队列,最后发送给消费端。

  所有需要给exchange、queue和message都进行持久化:

  exchange持久化:

  //第三个参数true表示这个exchange持久化
channel.exchangeDeclare(EXCHANGE_NAME, "direct", true);

  queue持久化:

  //第二个参数true表示这个queue持久化
channel.queueDeclare(QUEUE_NAME, true, false, false, null);

  message持久化:

  //第三个参数MessageProperties.PERSISTENT_TEXT_PLAIN表示这条消息持久化
channel.basicPublish(EXCHANGE_NAME, ROUTING_KEY, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes(StandardCharsets.UTF_8));

  这样,如果RabbitMQ收到消息后挂了,重启后会自行恢复消息。

  到此,RabbitMQ提供的几种机制都介绍完了,但这样还不足以保证消息可靠性投递RabbitMQ中,上面我也提到了会有极端情况,比如RabbitMQ收到消息还没来得及将消息持久化到硬盘时,RabbitMQ挂了,这样消息还是丢失了,或者RabbitMQ在发送确认消息给生产端的过程中,由于网络故障而导致生产端没有收到确认消息,这样生产端就不知道RabbitMQ到底有没有收到消息,就不好做接下来的处理。

  所以除了RabbitMQ提供的一些机制外,我们自己也要做一些消息补偿机制,以应对一些极端情况。接下来我就介绍其中的一种解决方案——消息入库。

  消息入库

  消息入库,顾名思义就是将要发送的消息保存到数据库中。

  首先发送消息前先将消息保存到数据库中,有一个状态字段status=0,表示生产端将消息发送给了RabbitMQ但还没收到确认;在生产端收到确认后将status设为1,表示RabbitMQ已收到消息。这里有可能会出现上面说的两种情况,所以生产端这边开一个定时器,定时检索消息表,将status=0并且超过固定时间后(可能消息刚发出去还没来得及确认这边定时器刚好检索到这条status=0的消息,所以给个时间)还没收到确认的消息取出重发(第二种情况下这里会造成消息重复,消费者端要做幂等性),可能重发还会失败,所以可以做一个最大重发次数,超过就做另外的处理。

  这样消息就可以可靠性投递到RabbitMQ中了,而生产端也可以感知到了。

  消费端消息不丢失

  既然已经可以让生产端100%可靠性投递到RabbitMQ了,那接下来就改看看消费端的了,如何让消费端不丢失消息。

  默认情况下,以下3种情况会导致消息丢失:

  在RabbitMQ将消息发出后,消费端还没接收到消息之前,发生网络故障,消费端与RabbitMQ断开连接,此时消息会丢失;

  在RabbitMQ将消息发出后,消费端还没接收到消息之前,消费端挂了,此时消息会丢失;

  消费端正确接收到消息,但在处理消息的过程中发生异常或宕机了,消息也会丢失。

  其实,上述3中情况导致消息丢失归根结底是因为RabbitMQ的自动ack机制,即默认RabbitMQ在消息发出后就立即将这条消息删除,而不管消费端是否接收到,是否处理完,导致消费端消息丢失时RabbitMQ自己又没有这条消息了。

  所以就需要将自动ack机制改为手动ack机制。

  消费端手动确认消息:

  DeliverCallback deliverCallback = (consumerTag, delivery) -> {
try {
//接收到消息,做处理
//手动确认
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
} catch (Exception e) {
//出错处理,这里可以让消息重回队列重新发送或直接丢弃消息
}
};
//第二个参数autoAck设为false表示关闭自动确认机制,需手动确认
channel.basicConsume(QUEUE_NAME, false, deliverCallback, consumerTag -> {});

  这样,当autoAck参数置为false,对于RabbitMQ服务端而言,队列中的消息分成了两个部分:一部分是等待投递给消费端的消息;一部分是已经投递给消费端,但是还没有收到消费端确认信号的消息。如果RabbitMQ一直没有收到消费端的确认信号,并且消费此消息的消费端已经断开连接或宕机(RabbitMQ会自己感知到),则RabbitMQ会安排该消息重新进入队列(放在队列头部),等待投递给下一个消费者,当然也有能还是原来的那个消费端,当然消费端也需要确保幂等性。

  好了,到此从生产端到RabbitMQ再到消费端的全链路,就可以保证数据的不丢失。

  由于个人水平有限,有些地方可能理解错了或理解不到位的,请大家多多指出!Thanks

  HAProxy从零开始到掌握

  系统架构性能问题诊断及优化思路

  Redis官方的高可用性解决方案

  亿级用户中心的设计与实践

  分布式事务最经典的七种解决方案

  免责声明:

  本公众号部分分享的资料来自网络收集和整理,所有文字和图片版权归属于原作者所有,且仅代表作者个人观点,与本公众号无关,文章仅供读者学习交流使用,并请自行核实相关内容,如文章内容涉及侵权,请联系后台管理员删除。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
探店宁波新式舞厅:全国各地美女齐聚,玩法新潮彻底颠覆老印象

探店宁波新式舞厅:全国各地美女齐聚,玩法新潮彻底颠覆老印象

成都人的故事
2026-07-20 21:05:07
伊布:西班牙在亚马尔不是100%状态下夺冠,说明了他们有多强

伊布:西班牙在亚马尔不是100%状态下夺冠,说明了他们有多强

懂球帝
2026-07-20 09:26:19
这几棍子太猛了,隔着屏幕都能感受到中国海警的愤怒!

这几棍子太猛了,隔着屏幕都能感受到中国海警的愤怒!

阿龙聊军事
2026-07-20 21:59:33
这名女子被全网骂!国歌响起不站立,玩手机引众怒,网友要求开除

这名女子被全网骂!国歌响起不站立,玩手机引众怒,网友要求开除

谭谈社会
2026-07-19 19:50:45
两性心理学:男人出轨,想方设法往酒店带,女人出轨,不知不觉往家里领,这不是偶然,而是必然

两性心理学:男人出轨,想方设法往酒店带,女人出轨,不知不觉往家里领,这不是偶然,而是必然

心理观察局
2026-07-19 07:01:19
今年立秋不一般!8月7日夜里交节,立秋之后还要热多久?

今年立秋不一般!8月7日夜里交节,立秋之后还要热多久?

周哥一影视
2026-07-20 10:57:55
深圳地铁实现进站安检全覆盖,新规首日大排长龙,官方温馨提醒

深圳地铁实现进站安检全覆盖,新规首日大排长龙,官方温馨提醒

21世纪经济报道
2026-07-20 18:04:18
丢冠又输人!阿根廷恶汉赛后闹事:锁喉+拳击 将2人打翻在地

丢冠又输人!阿根廷恶汉赛后闹事:锁喉+拳击 将2人打翻在地

叶青足球世界
2026-07-20 07:06:27
谢贤生前最后露面曝光,谢霆锋雇人24小时三班制照顾谢贤

谢贤生前最后露面曝光,谢霆锋雇人24小时三班制照顾谢贤

鲁中晨报
2026-07-20 17:28:36
小杨阿姨独自在湾湾看家,箖箖和玥儿已回北京,透露接下来安排!

小杨阿姨独自在湾湾看家,箖箖和玥儿已回北京,透露接下来安排!

猪小艳吖
2026-07-21 01:39:28
高敬亭被冤杀的责任主要该由谁承担?争议了几十年,只有邓子恢坦然表示:我是有责任的

高敬亭被冤杀的责任主要该由谁承担?争议了几十年,只有邓子恢坦然表示:我是有责任的

人生录
2026-07-21 00:05:07
世界杯落幕不到 24 小时,最终排名奖金曝光,却出现令人恶心的一

世界杯落幕不到 24 小时,最终排名奖金曝光,却出现令人恶心的一

锅锅爱历史
2026-07-20 20:05:44
世界杯 | 阿根廷主帅泪洒发布会:失利让人心如刀割

世界杯 | 阿根廷主帅泪洒发布会:失利让人心如刀割

新京报
2026-07-20 10:38:13
奥塔门迪挑衅罗德里险起冲突,对话内容曝光:蠢货,你哭了一整周

奥塔门迪挑衅罗德里险起冲突,对话内容曝光:蠢货,你哭了一整周

而长终
2026-07-21 04:30:51
发现马上扔!男子吃完直接肝衰竭!医生:比砒霜还毒,煮熟也没用

发现马上扔!男子吃完直接肝衰竭!医生:比砒霜还毒,煮熟也没用

华庭讲美食
2026-07-19 00:17:18
沈醉晚年道出秘闻:国民党高层胡宗南明明知道自己的秘书熊向晖是中共卧底,却刻意包庇究竟是为什么?

沈醉晚年道出秘闻:国民党高层胡宗南明明知道自己的秘书熊向晖是中共卧底,却刻意包庇究竟是为什么?

唠叨说历史
2026-07-13 18:03:40
太敢拍了!53岁格温妮丝全裸出镜被骂上热搜,商业帝国打脸全网

太敢拍了!53岁格温妮丝全裸出镜被骂上热搜,商业帝国打脸全网

知法而形
2026-07-19 17:05:30
更多现场画面公开,菲律宾船员非常嚣张,直接用船桨攻击中方执法人员

更多现场画面公开,菲律宾船员非常嚣张,直接用船桨攻击中方执法人员

三叔的装备空间
2026-07-20 23:35:55
深圳斯诺克公开赛!5-0,0-5中国4胜1负,3场惨案,刘宏宇5连鞭!

深圳斯诺克公开赛!5-0,0-5中国4胜1负,3场惨案,刘宏宇5连鞭!

米师傅安装
2026-07-21 04:47:47
美媒排名:现役最强三巨头!新王登基!雷马三少掉队?

美媒排名:现役最强三巨头!新王登基!雷马三少掉队?

篮球盛世
2026-07-20 13:58:49
2026-07-21 06:27:00
IT架构师联盟 incentive-icons
IT架构师联盟
IT架构实战分享
844文章数 7672关注度
往期回顾 全部

科技要闻

网易科技"未来大奖2026上半年AI榜单"揭晓

头条要闻

媒体:驱逐所有以色列人 马来西亚对以强硬几乎零成本

头条要闻

媒体:驱逐所有以色列人 马来西亚对以强硬几乎零成本

体育要闻

65岁肌肉男,世界杯最年长冠军主帅

娱乐要闻

谢霆锋发文确认父亲谢贤去世 享年89岁

财经要闻

AI开始挤泡沫

汽车要闻

综合续航超1600km 2027款星途ES上市置换价16.99万起

态度原创

房产
教育
健康
旅游
公开课

房产要闻

北师附、人大附、西侨、丘海…招生、划片最新变化来了!

教育要闻

大女儿一下治好了爸爸的哑巴!姐弟互动视频火了,爸爸偏心太明显

“斑块”患者要小心中风?

旅游要闻

心疼落魄帝王,铭记抗清英雄,一座磨盘山装着云南人放不下的情怀

公开课

李玫瑾:为什么性格比能力更重要?

无障碍浏览 进入关怀版