一、消息如何保证可靠性传输

1.1、可能出现消息丢失的情况

  1、Producer在把Message发送Broker的过程中,因为网络问题等发生丢失,或者Message到了Broker,但是出了问题,没有保存下来

  针对这个问题,Producer可以开启MQ的事务,如果这个过程出现异常,进行回滚,但是有个很大的问题,你提交一个事务就会阻塞在那,

非常影响性能,生产环境肯定不会开启事务,一般都是使用confirm机制

  2、Broker接收到Message暂存到内存,Consumer还没来得及消费,Broker挂掉了

  可以通过持久化设置去解决:

    1).创建Queue的时候设置持久化,保证Broker持久化Queue的元数据,但是不会持久化Queue里面的消息

    2).将Message的deliveryMode设置为2,可以将消息持久化到磁盘,这样只有Message支持化到磁盘之后才会发送通知Producer ack

  这两步过后,即使Broker挂了,Producer肯定收不到ack的,就可以进行重发

  3、Consumer有消费到Message,但是内部出现问题,Message还没处理,Broker以为Consumer处理完了,只会把后续的消息发送

  这时候,就要关闭autoack,消息处理过后,进行手动ack

1.2、一般通过生产端保证可靠性投递

  1、保证消息的成功发出

  2、保证MQ节点的成功接收

  3、发送端收到MQ节点(Broker)的确认应答

  4、完善的消息补偿机制

1.3、解决方案

1、消息落库,对消息状态进行变更,对于高并发环境下数据库压力很大,因为需要写多次数据库

整体流程:

  1、业务数据和消息都进行落库

  2、生产端发送message给Broker

  3、Broker给Confirm响应返回生产端

  4、接收到confirm,对message状态更改

  5、分布是定时任务获取消息的状态

  6、如果消息不能成功投递,重新进行发送,记录重发次数

  7、当重发3次之后,将状态修改,只能人工进行干预

2、消息的延迟投递,做二次确认,回调检查。适合高并发环境,减少写库的次数

整体流程:

  1、上游服务首先将业务代码入库,发送message给Broker

  2、发送第二个延迟确认消息

  3、下游服务监听消息进行消费

  4、发送确认消息,这里不是confirm机制,而是一条新的消息

  5、通过回调服务监听这个confirm消息,然后把消息进行入库

  6、回调服务检查到延迟确认消息,会数据库查询是否有这条消息

  7、如果没有查到这条消息,回调服务通过RPC给一个重新发送命令到上游系统

相比第一种方案,这里减少了一次message入库,confirm机制是消息可靠性投递的一个核心,在下篇文章会讲到

二、如何保证消息的幂等性

  首先,无论是RabbitMQ、RocketMQ还是kafka,都有可能出现消息的重复发送,这个是MQ无法保障的,而幂等性是开发或者运维人员需要保证的

  所谓消息的幂等性是指即使收到多次消息,也不会重复消费,这点很重要,例如用户付钱,点的太快了,付了多次,但是你也只能扣一次钱,

不然要骂人了

2.1、RabbitMQ可能导致出现非幂等性的情况

  1、可靠性消息投递机制:consumer回复confirm出现网络闪断,producer没有收到ack,定时任务轮询可能就会重新发送消息,这样consumer就

会收到两条消息

  2、MQ Broker与消费端传输消息的过程出现网络抖动

  3、消费端故障或异常

2.2、kafka可能出现非幂等性的情况

在Consumer端offset没有提交的时候,Consumer重启了,这时候就会出现重复消费的情况

2.3、解决方案

1、唯一ID+指纹码

  整体实现相对简单,需要进行数据库写入,利用数据库主键去重,使用ID进行分库分表算法路由,从单库的幂等性到多库的幂等性

  1).这里唯一ID一般就是业务表的主键,比如商品ID

  2).指纹码:每次操作都要生成指纹码,可以用时间戳+业务编号+...组成,目的是保证每次操作都是正常的

整体流程:

  1、需要一个统一ID生成服务,为了保证可靠性,上游服务也要有个本地ID生成服务,然后发送消息给Broker

  2、需要ID规则路由组件去监听消息,先入库,如果入库成功,证明没有重复,然后发给下游,如果发现库里面有了这条消息,就不发给下游

2、利用Redis的原子性实现

  Redis的实现性能比较好,而且Redis一般使用集群,不用担心某台机器挂掉了,影响服务。

存在的问题:

  是否要进行数据落库,如果落库的话,怎么保证缓存和storage的一致性、事务,如果不落库,如何设置定时同步策略

RabbitMQ系列(四)--消息如何保证可靠性传输以及幂等性的更多相关文章

  1. rabbitmq系列四 之路由

    1.路由 在上一个的教程中,我们构建了一个简单的日志记录系统.我们能够向许多接收者广播日志消息. 在本次教程中,我们向该系统添加一些特性,比如,我只需要严重错误(erroe级别)的部分日志打印到磁盘文 ...

  2. 9. RabbitMQ系列之消息发布确认

    Publisher Confirms发布确认是用于实现可靠发布的RabbitMQ扩展. 我们将使用发布确认来确保已发布的消息已安全到达代理.我们将介绍几种使用publisher确认的策略,并解释其优缺 ...

  3. 四种途径提高RabbitMQ传输消息数据的可靠性(一)

    前言 RabbitMQ虽然有对队列及消息等的一些持久化设置,但其实光光只是这一个是不能够保障数据的可靠性的,下面我们提出这样的质疑: (1)RabbitMQ生产者是不知道自己发布的消息是否已经正确达到 ...

  4. RabbitMQ系列(四)RabbitMQ事务和Confirm发送方消息确认——深入解读

    RabbitMQ事务和Confirm发送方消息确认--深入解读 RabbitMQ系列文章 RabbitMQ在Ubuntu上的环境搭建 深入了解RabbitMQ工作原理及简单使用 RabbitMQ交换器 ...

  5. RabbitMQ消息可靠性传输

    消息的可靠性投递是使用消息中间件不可避免的问题,不管是使用kafka.rocketMQ或者rabbitMQ,那么在RabbitMQ中如何保证消息的可靠性投递呢? 先再看一下RabbitMQ消息传递的流 ...

  6. kafka系列四、kafka架构原理、高可靠性存储分析及配置优化

    一.概述 Kakfa起初是由LinkedIn公司开发的一个分布式的消息系统,后成为Apache的一部分,它使用Scala编写,以可水平扩展和高吞吐率而被广泛使用.目前越来越多的开源分布式处理系统如Cl ...

  7. 转:TCP为什么要3次握手和4次挥手时等待2MSL、 TCP如何保证消息顺序以及可靠性到达

    关于tcp三次握手.四次挥手可以看这里:TCP与UDP的差别以及TCP三次握手.四次挥手 1.TCP为甚要3次握手? 在谢希仁著<计算机网络>第四版中讲“三次握手”的目的是“为了防止已失效 ...

  8. Netty4.x中文教程系列(四) 对象传输

    Netty4.x中文教程系列(四)  对象传输 我们在使用netty的过程中肯定会遇到传输对象的情况,Netty4通过ObjectEncoder和ObjectDecoder来支持. 首先我们定义一个U ...

  9. [2017-10-25]Abp系列——集成消息队列功能(基于Rebus.Rabbitmq)

    本系列目录:Abp介绍和经验分享-目录 前言 由于提交给ABP作者的集成消息队列机制的PR还未Review完成,本篇以Abplus中的代码为基准来介绍ABP集成消息队列机制的方案. Why 为什么需要 ...

随机推荐

  1. iOS下JSON反序列化开源库

    iOS下JSON字符串反序列化成对象.在正式的项目中比較常见.例如以下几个经常使用开源库.能够依据个人喜好任选其一: 1. JSONModel: https://github.com/icanzilb ...

  2. 多button事件处理

    private void ButtonClick(object sender, RoutedEventArgs e) { Button cmd = (Button)e.OriginalSource; ...

  3. js jquery验证上传文件的格式和大小

    // 验证附件格式和大小 function confirmData() { var flag = true; var message = ""; var errorSize = & ...

  4. lamdba匿名函数 sored()函数 filter()函数 map函数() 递归函数

    帅爆太阳的男人 1,lamdba匿名函数:为了解决一下简单的需求而设计的一句话函数,语法: 函数名 = lambda 参数: 返回值 def func(n): return n*n print(fun ...

  5. 利用JProfile 7分析内存OOM

    今天发现一个OOM问题,想来可能是有部分内存没有正确释放导致的 于是想到了之前使用的JProfile来分析一下 由于大概知道哪个类没有释放,可以在Memory Views里看一下对应的类有多少实例来确 ...

  6. Android系统定制----删除系统锁屏功能【转】

    本文转载自:http://blog.csdn.net/morixinguan/article/details/56675914 frameworks/base/packages/SettingsPro ...

  7. BaezaYates 交集python和golang代码

    def bsearch(find, arr, low, high): while low <= high: mid = (low + high) >> 1 if arr[mid] = ...

  8. 蓝书4.1-4.4 树状数组、RMQ问题、线段树、倍增求LCA

    这章的数据结构题很真实 T1 排队 bzoj 1699 题目大意: 求静态一些区间的最大值-最小值 思路: ST表裸题 #include<iostream> #include<cst ...

  9. 【SDOI 2008】 递归数列

    [题目链接] 点击打开链接 [算法] 矩阵乘法优化递推 由于本博客不支持数学公式,所以不能将矩阵画出来,请谅解! [代码] #include<bits/stdc++.h> using na ...

  10. POJ1584 A Round Peg in a Ground Hole 凸包判断 圆和凸包的关系

    POJ1584 题意:给定n条边首尾相连对应的n个点 判断构成的图形是不是凸多边形 然后给一个圆 判断圆是否完全在凸包内(相切也算) 思路:首先运用叉积判断凸多边形 相邻三条边叉积符号相异则必有凹陷 ...