RabbitMQ 消息 100% 投递的解决方案!

Stella981
• 阅读 466

RabbitMQ 消息 100% 投递的解决方案!

Java技术栈

www.javastack.cn

关注阅读更多优质文章

[

](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzI3ODcxMzQzMw%3D%3D%26mid%3D2247486559%26idx%3D2%26sn%3D0eebf45617fb7be5727712e22aac7fb6%26scene%3D21%23wechat_redirect)

一、前言

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

今天我们就来研究一下如何确保消息的100%的投递。

二、先谈谈 RabbitMQ 的特性

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

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

  1. 你需要进行手动应答,

  2. 最起码 Broker 不挂,且消息进行了持久化等。

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

  1. 消息成功的发送了出去

  2. 保证 Broker 成功的收到了消息

  3. 生产者收到了 Broker 的确认应答

  4. 消息补偿机制,当前三步都跪了,做一个补偿重发机制

  5. 最后一道屏障,如果第四步重试次数过多,那么说明系统出现问题,我们就需要人工干预了

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

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

3.1 先上一个示意图

RabbitMQ 消息 100% 投递的解决方案!

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技术栈,在后台回复:面试,可以获取我整理的 RabbitMQ 系列面试题和答案,非常齐全。

作者:热心市民小陈
链接:blog.csdn.net/weixin_42849915/article/details/87828163
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

RabbitMQ 消息 100% 投递的解决方案!

RabbitMQ 消息 100% 投递的解决方案!

RabbitMQ 消息 100% 投递的解决方案!

RabbitMQ 消息 100% 投递的解决方案!

RabbitMQ 消息 100% 投递的解决方案!

RabbitMQ 消息 100% 投递的解决方案!

RabbitMQ 消息 100% 投递的解决方案!

关注Java技术栈看更多干货

RabbitMQ 消息 100% 投递的解决方案!

RabbitMQ 消息 100% 投递的解决方案!

戳原文,获取精选面试题!

本文分享自微信公众号 - Java技术栈(javastack)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
MySQL 的慢 SQL 怎么优化?
!(https://oscimg.oschina.net/oscnet/7b00ec583b5e42cc80e8c56c6556c082.jpg)Java技术栈www.javastack.cn关注阅读更多优质文章(https://www.oschina.net/action/GoToLink?urlhttp
Stella981 Stella981
3年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Stella981 Stella981
3年前
Spring Boot 2.1.6 发布了!
!(https://oscimg.oschina.net/oscnet/e5aaab7a5b9f4aa7a944b00aff253ed2.jpg)Java技术栈www.javastack.cn优秀的Java技术公众号(https://www.oschina.net/action/GoToLink?urlhttps%3
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这