Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >超级好用的RabbitMQ 消息 100% 投递的解决方案!

超级好用的RabbitMQ 消息 100% 投递的解决方案!

原创
作者头像
程序员白楠楠
修改于 2021-01-21 03:16:22
修改于 2021-01-21 03:16:22
6850
举报

一、前言

现在大多都使用 MQ 来做系统的异构,来做系统的解耦,系统的的模块相当于寄信者与收信者,MQ 则扮演者邮局的角色。作为一个中转的角色,就需要确保消息的100%投递。

今天我们就来研究一下如何确保消息的100%的投递。整理了一份Java面试宝典完整版PDF

二、先谈谈 RabbitMQ 的特性

RabbitMQ 所做的确保是:只要你把消息投递到 Broker 中,那么我就确保这个消息会送达到消费者的手中。

当然这是有前提条件的,比如:

  1. 你需要进行手动应答,
  2. 最起码 Broker 不挂,且消息进行了持久化等。

结合 RabbitMQ 的特性来做分析,针对于投递端,我们只需要确保把消息发送到 Broker 中即可,那么如何保证可靠性呢,分下列步骤:

  1. 消息成功的发送了出去
  2. 保证 Broker 成功的收到了消息
  3. 生产者收到了 Broker 的确认应答
  4. 消息补偿机制,当前三步都跪了,做一个补偿重发机制
  5. 最后一道屏障,如果第四步重试次数过多,那么说明系统出现问题,我们就需要人工干预了

只要做到上面五步,基本上我们就可以保证,消息投递100%的投递出去。另外,关注公众号Java技术栈,在后台回复:面试,可以获取我整理的 RabbitMQ 系列面试题和答案,非常齐全。

三、生产者的投递的可靠性保障

3.1 先上一个示意图

3.2 就上述的图示,我们逐步解析
  • step1:数据落库,这一步是必须的
  • step2:把消息落库,且初始化其状态为 0 (发送中)
  • step3:把消息投递到 Broker 中
  • step4:Broker 发送成功应答
  • step5:生产者拿到成功应答,修改消息状态为1:(发送成功) 上面讲述的都是正常的流程,下面讲讲如果出现不正常的解决机制:
  • step6:定时检查消息的状态是否为1
  • step7:如果 step6 的消息的状态仍然为 0 ,则进入重发,重复上述 step1 - step5
  • step8:如果消息重发达到一定的的次数,则人工接入处理,因为此时说明可能是消息

上述的方案看似完美无缺,但是细想,如果在 step4 中 Broker 发送应答的过程中,网络出现问题这个消息没有到达生产者会导致整个流程进入补偿的流程当中,此时 Broker 中就有两条消息,也就是发成了重复的投递的问题,所以接下来我们要在消费端来处理这个问题。

四、消费端的幂等:

4.1 导致需要解决幂等的原因
  • Broker 发送应答消息的时候,消息未到达生产者
  • 消费者在发送应答的时候,消费者挂掉了
4.2 就上述我们的机制的解决

因为上述我的消息都有唯一的标识,所以我们只需要查找对应的消息对应的标识来判断其状态即可。

4.3 构建唯一标识的方案

首先说明不同的方案使用不同的应用场景,不要一上来你就说十几万的并发怎么样的,这个慢慢来,一步步往这里走。

4.3.1 利用数据库自增id
优点:

1):不能再简单了,在并发不大的情况可以接受

2):对分页和排序是有帮助的

缺点:

1):分库分表和读写分离多住从的情况下不适用

2):性能达不到要求时,不利于扩展

3):不同数据库的语法实现不一样

4.3.2 利用 redis 来生成id
优点:

1):redis 单线程可以生成全局唯一ID

2):可以使用 redis 集群获取更高的吞吐量

缺点:

1):引入新的组件,增加系统复杂度

2):需要注意处理并发问题

4.3.3 利用 twitter 开源的 snowflake

snowflake 是 twitter 开源的一个分布式的 ID 的生成算法,结果是一个 long 的ID,使用 41bit 作为毫秒数,10bit 作为机器 ID(5个 bit 是数据中心,5个 bit 是机器 ID) 12 bit 作为毫秒内的流水号(每个节点每毫秒可以产生 2^12 = 4096 个 ID)最后是一个符号位。

优点:

不依赖数据库和其他的中间件,且性能尚可

缺点:

是有依赖时间的,如果各个机器的失重不同步就会出现不适全局递增的情况。整理了一份Java面试宝典完整版PDF

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
RabbitMQ消息的100%投递 顶
上图中BIZ DB为我们的业务库,比方说保存订单;MSG DB为消息库,保存我们发送到MQ消息。如果在Step 3的时候,网络出现故障,Confirm机制没有收到broker的消息确认。我们需要设置一个时间临界点,比如说5分钟,检索出消息库中状态为0的消息,通过分布式定时任务,比如XXL-Job或者Elastic-Job。但有可能出现消息刚发出去,还没有Confirm成功,定时任务就已经启动了,并把发送成功的消息确认为未成功,所以我们需要有一个Step 6,给入库消息一个最大的容忍时间,比如说2分钟到5分钟。比如消息入库的时候需要带上时间,我们取出状态为0的消息形成一个集合,然后过滤该集合的时间为2分钟以上的消息进行重新发送。由于MQ消息的配置本身有问题的情况下(比如说路由,队列,交换机),会出现消息永远无法发送成功,这个时候我们需要有一个消息重试的机制,比如3次,如果3次都没有发送成功,则更新该消息状态为2,表示失败。
算法之名
2019/12/16
4150
RabbitMQ消息的100%投递
                                                                            顶
Python之Rabbitmq处理消息
Broker:简单来说就是消息队列服务器实体。 Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列。 Queue:消息队列载体,每个消息都会被投入到一个或多个队列。是Rabbitmq的内部对象,用于存储消息 Binding:绑定,它的作用就是把Exchange和Queue按照路由规则绑定起来。 Routing Key:路由关键字,Exchange根据这个关键字进行消息投递。 Vhost:虚拟主机,一个Broker里可以开设多个Vhost,用作不同用户的权限分离。 Producer:消息生产者,就是投递消息的程序。 Consumer:消息消费者,就是接受消息的程序。 Channel:消息通道,在客户端的每个连接里,可建立多个Channel,每个Channel代表一个会话任务。
Wu_Candy
2022/07/04
5300
Python之Rabbitmq处理消息
RabbitMQ知识点整理总结
答:采用AMQP高级消息队列协议的一种消息队列技术,最大的特点就是消费并不需要确保提供方存在,实现了服务之间的高度解耦
用户7353950
2022/06/23
6980
RabbitMQ知识点整理总结
RabbitMQ之消息可靠性投递解读
producer->exchange:确保消息发送到RabbitMQ服务器的交换机上
一个风轻云淡
2023/10/13
5590
非常强悍的 RabbitMQ 总结,写得真好!
RabbitMQ是基于AMQP协议的,通过使用通用协议就可以做到在不同语言之间传递。
程序员白楠楠
2021/01/12
1.8K0
RabbitMQ消息队列之实现可靠投递的请求-确认机制
使用 RabbitMQ 时,消息发送方期望杜绝任何消息丢失或投递失败场景(否则 MQ 将失去其存在意义)。RabbitMQ 提供两个选项控制消息的投递可靠性模式。
JavaEdge
2021/02/22
1.2K0
RabbitMQ消息队列之实现可靠投递的请求-确认机制
RabbitMQ消息中间件 高级篇二 高并发情况下保障消息投递可靠性
高并发场景下,消息的延迟投递做二次确认进行回调检查来保障生产者消息投递成功的可靠性
凯哥Java
2019/07/22
8740
RabbitMQ消息中间件 高级篇二 高并发情况下保障消息投递可靠性
RabbitMQ高级篇一 本章导航及BAT大厂如何保障生产端可靠性投递
1:当有消息到达后,先将消息信息入库到BIZDB库中(消息状态为0 发送中),同时将需要发送给下一个系统的消息也进行入库。如果都两此入库都没有异常信息,再有sender进行发送。
凯哥Java
2019/07/19
4260
RabbitMQ高级篇一 本章导航及BAT大厂如何保障生产端可靠性投递
【RabbitMQ】如何进行消息可靠投递【上篇】
前几天,突然发生线上报警,钉钉连发了好几条消息,一看是RabbitMQ相关的消息,心头一紧,难道翻车了?
弗兰克的猫
2019/09/29
1.1K1
【RabbitMQ】如何进行消息可靠投递【上篇】
rabbitmq之可靠性投递与生产实践(二)
首先需要明确,效率与可靠性是无法兼得的,如果要保证每一个环节都成功,势必会对消息的收发效率造成影响。 如果是一些业务实时一致性要求不是特别高的场合,可以牺牲一些可靠性来换取效率。
周杰伦本人
2022/10/25
4890
rabbitmq之可靠性投递与生产实践(二)
RabbitMQ消息的可靠性投递
在项目中使用RabbitMQ时,我们可能会遇到这样的问题:如一个订单系统当用户付款成功时我们往消息中间件添加一条记录期望消息消费者修改订单状态,但是最终实际订单状态并没有被修改成功。遇到这种问题我们排查的思路如下:
诺浅
2020/08/21
1.2K0
聊聊业务系统中投递消息到mq的几种方式
step5:新增一个定时器,轮询t_msg_record,将待发送的记录投递到mq中
路人甲Java
2019/12/11
6610
rabbitmq常见面试题「建议收藏」
1.解耦,系统A在代码中直接调用系统B和系统C的代码,如果将来D系统接入,系统A还需要修改代码,过于麻烦!
全栈程序员站长
2022/09/09
1.3K0
rabbitmq常见面试题「建议收藏」
精选RabbitMQ面试题[45题]
RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件)。RabbitMQ服务器是用Erlang语言编写的,而群集和故障转移是构建在开放电信平台框架上的。所有主要的编程语言均有与代理接口通讯的客户端库。
一行Java
2022/04/07
1.7K0
精选RabbitMQ面试题[45题]
程序员的20大RabbitMQ面试问题及答案
RabbitMQ 是一款开源的,Erlang 编写的,基于 AMQP 协议的,消息中间件;
鱼找水需要时间
2023/12/25
1.1K0
面试必备(背)-RabbitMQ八股文系列!
RabbitMQ 就是 AMQP 协议的 Erlang 的实现(当然 RabbitMQ 还支持 STOMP2、 MQTT3 等协议 ) AMQP 的模型架构和 RabbitMQ 的模型架构是一样的,生产者将消息发送给交换器,交换器和队列绑定 。
微客鸟窝
2022/05/24
2.1K0
面试必备(背)-RabbitMQ八股文系列!
深度剖析RabbitMQ可靠性消息投递以及实践方案
一般而言,如果你选择RabbitMQ,那肯定就是把可靠性放在第一位。毕竟,RabbitMQ可是金融行业消息队列的标配。如果把性能放在第一位,那毫无疑问,必须是Kafka。但是,可靠性毕竟是相对的,就拿大火的阿里云,AWS云,或者传统的IBM小型机,Oracle数据库,没有谁敢说自己可靠性100%,都是说几个9。所以,本文的目的很明确,就是尽可能的提高我们RabbitMQ的可靠性,从发送、存储、消费、集群、监控、告警等多个维度给出可行性方案,指导开发者以及运维人员获取更加可靠的消息投递,保障我们的业务系统安全、可靠、稳定的运行。
程序猿DD
2020/05/26
9600
深度剖析RabbitMQ可靠性消息投递以及实践方案
RabbitMQ生产端消息可靠性投递方案分析
导文: 1.什么是RabbitMQ 2.Java开发技术大杂烩(三)之电商项目优化、rabbitmq、Git、OSI、VIM、Intellj IDEA、HTTP、JS、Java
用户2032165
2018/12/07
1.8K0
【消息队列之rabbitmq】Rabbitmq之消息可靠性投递和ACK机制实战
上篇文章介绍了rabbitmq的基本知识、交换机类型实战《【消息队列之rabbitmq】学习RabbitMQ必备品之一》 这篇文章主要围绕着消息确认机制为中心,展开实战;接触过消息中间件的伙伴都知道,消息会存在以下问题: 1、消息丢失问题和可靠性投递问题; 2、消息如何保证顺序消费; 3、消息如何保证幂等性问题,即重复消费问题等等… 本文主要以Rabbitmq消息中间件解决问题一的实践,其他问题小编会重新写文章总结;
沁溪源
2022/01/13
1.3K0
【消息队列之rabbitmq】Rabbitmq之消息可靠性投递和ACK机制实战
rabbitmq整个消息投递的路径
rabbitmq整个消息投递的路径是producer—>rabbitmq broker—>exchange—>queue—>consumer。 生产者将消息投递到Broker时产生confirm状态,会出现二种情况,ack:表示已经被Broker签收。nack:表示表示已经被Broker拒收,原因可能有队列满了,限流,IO异常等。生产者将消息投递到Broker,被Broker签收,但是没有对应的队列进行投递,将消息回退给生产者会产生return状态。这二种状态是rabbitmq提供的消息可靠投递机制,生产者开启确认模式和退回模式。使用rabbitTemplate.setConfirmCallback设置回调函数。当消息发送到exchange后回调confirm方法。在方法中判断ack,如果为true,则发送成功,如果为false,则发送失败,需要处理。使用rabbitTemplate.setReturnCallback设置退回函数,当消息从exchange路由到queue失败后,如果设置了rabbitTemplate.setMandatory(true)参数,则会将消息退回给producer。消费者在rabbit:listener-container标签中设置acknowledge属性,设置ack方式 none:自动确认,manual:手动确认。none自动确认模式很危险,当生产者发送多条消息,消费者接收到一条信息时,会自动认为当前发送的消息已经签收了,这个时候消费者进行业务处理时出现了异常情况,也会认为消息已经正常签收处理了,而队列里面显示都被消费掉了。所以真实开发都会改为手动签收,可以防止消息丢失。消费者如果在消费端没有出现异常,则调用channel.basicAck方法确认签收消息。消费者如果出现异常,则在catch中调用 basicNack或 basicReject,拒绝消息,让MQ重新发送消息。通过一系列的操作,可以保证消息的可靠投递以及防止消息丢失的情况。
用户11220026
2024/07/26
1640
推荐阅读
相关推荐
RabbitMQ消息的100%投递 顶
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档