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

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. SUSE Linux源代码编译安装MySQL 5.6

    这篇文章主要介绍了SUSE Linux下源代码编译方式安装MySQL 5.6过程分享,本文使用SUSE Linux Enterprise Server 10 SP3 (x86_64)系统,须要的朋友能 ...

  2. 【跟我一步一步学Struts2】——登陆样例

    本篇博客通过一个简单的登陆小样例来入门,简单了解一下struts2是怎样工作的: 第一步引入Jar包: commons-fileupload-1.2.1.jar,文件上传 commons-loggin ...

  3. win32gui.EnumWindows my.os.EnumWindows.py

    import win32guidef _MyCallback(hwnd, extra): windows = extra temp = [] temp.append(hex(hwnd)) temp.a ...

  4. YTU 2517: 打倒魔王↖(^ω^)↗

    2517: 打倒魔王↖(^ω^)↗ 时间限制: 1 Sec  内存限制: 128 MB 提交: 231  解决: 112 题目描述 从前有一个王子,他喜欢上了邻国的一个公主.终于有一天他向公主表白了, ...

  5. Lexer and parser generators (ocamllex, ocamlyacc)

    Chapter 12 Lexer and parser generators (ocamllex, ocamlyacc) This chapter describes two program gene ...

  6. POJ 2104 HDU 2665 主席树 解决区间第K大

    两道题都是区间第K大询问,数据规模基本相同. 解决这种问题, 可以采用平方划分(块状表)复杂度也可以接受,但是实际表现比主席树差得多. 这里大致讲一下我对主席树的理解. 首先,如果对于某个区间[L,R ...

  7. LED全彩显示屏色度空间

    摘要:LED全彩显示屏.LED电子大屏幕如果要有一个良好的视觉效果,其中色度占有一席重要的位置,那么该如何让LED显示屏的色度更均匀.合理呢,下面为大家总结出以下几点,供大家参考. LED全彩显示屏. ...

  8. MSP430:实时时钟-DS1302

    /* * DS1302.h * * Created on: 2013-11-27 * Author: Allen */ #ifndef DS1302_H_ #define DS1302_H_ #inc ...

  9. 1617: [Usaco2008 Mar]River Crossing渡河问题(dp)

    1617: [Usaco2008 Mar]River Crossing渡河问题 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1219  Solved:  ...

  10. serlvet HttpServletRequest

    1.http://localhost/az/servlet/TestResponse out.print("getServletPath:"+request.getServletP ...