避免MQ消息重发的简单实现思路
一、MQ消息发送
一、MQ消息发送

1、发送端MQ-client(消息生产者:Producer)将消息发送给MQ-server;
2、MQ-server将消息落地;
3、MQ-server回ACK给MQ-client(Producer);
4、MQ-server将消息发送给消息接受端MQ-client(消息消费者:Customer);
5、MQ-client(Customer)消费接受到消息后发送ACK给MQ-server;
6、MQ-server将落地消息删除
二、消息重复发送原因
为了保证消息必达,MQ使用了消息超时、重传、确认机制。使得消息可能被重复发送,如上图中,由于网络不可达原因:3和5中断,可能导致消息重发。消息生产者a收不到MQ-server的ACK,重复向MQ-server发送消息。MQ-server收不到消息消费者b的ACK,重复向消息消费者b发消息。
三、消息重复发送产生的后果
举个例子:购买会员卡,上游支付系统负责给用户扣款,下游系统负责给用户发卡,通过MQ异步通知。不管是上半场的ACK丢失,导致MQ收到重复的消息,还是下半场ACK丢失,导致购卡系统收到重复的购卡通知,都可能出现,上游扣了一次钱,下游发了多张卡。
四、MQ内部如何做到幂等性的
对于每条消息,MQ内部生成一个全局唯一、与业务无关的消息ID:inner-msg-id。当MQ-server接收到消息时,先根据inner-msg-id判断消息是否重复发送,再决定是否将消息落地到DB中。这样,有了这个inner-msg-id作为去重的依据就能保证一条消息只能一次落地到DB。
五、消息消费者应当如何做到幂等性
1、对于非幂等性业务且要求实现幂等性业务:生成一个唯一ID标记每一条消息,将消息处理成功和去重日志通过事物的形式写入去重表。
2、对于非幂等性业务可不实现幂等性的业务:权衡去重所花的代价决定是否需要实现幂等性,如:购物会员卡成功,向用户发送通知短信,发送一次或者多次影响不大。不做幂等性可以省掉写去重日志的操作。
1、发送端MQ-client(消息生产者:Producer)将消息发送给MQ-server;
2、MQ-server将消息落地;
3、MQ-server回ACK给MQ-client(Producer);
4、MQ-server将消息发送给消息接受端MQ-client(消息消费者:Customer);
5、MQ-client(Customer)消费接受到消息后发送ACK给MQ-server;
6、MQ-server将落地消息删除
二、消息重复发送原因
为了保证消息必达,MQ使用了消息超时、重传、确认机制。使得消息可能被重复发送,如上图中,由于网络不可达原因:3和5中断,可能导致消息重发。消息生产者a收不到MQ-server的ACK,重复向MQ-server发送消息。MQ-server收不到消息消费者b的ACK,重复向消息消费者b发消息。
三、消息重复发送产生的后果
举个例子:购买会员卡,上游支付系统负责给用户扣款,下游系统负责给用户发卡,通过MQ异步通知。不管是上半场的ACK丢失,导致MQ收到重复的消息,还是下半场ACK丢失,导致购卡系统收到重复的购卡通知,都可能出现,上游扣了一次钱,下游发了多张卡。
四、MQ内部如何做到幂等性的
对于每条消息,MQ内部生成一个全局唯一、与业务无关的消息ID:inner-msg-id。当MQ-server接收到消息时,先根据inner-msg-id判断消息是否重复发送,再决定是否将消息落地到DB中。这样,有了这个inner-msg-id作为去重的依据就能保证一条消息只能一次落地到DB。
五、消息消费者应当如何做到幂等性
1、对于非幂等性业务且要求实现幂等性业务:生成一个唯一ID标记每一条消息,将消息处理成功和去重日志通过事物的形式写入去重表。
2、对于非幂等性业务可不实现幂等性的业务:权衡去重所花的代价决定是否需要实现幂等性,如:购物会员卡成功,向用户发送通知短信,发送一次或者多次影响不大。不做幂等性可以省掉写去重日志的操作。

避免MQ消息重发的简单实现思路的更多相关文章
- MQ解决消息重发--做到幂等性
一.MQ消息发送 1.发送端MQ-client(消息生产者:Producer)将消息发送给MQ-server: 2.MQ-server将消息落地: 3.MQ-server回ACK给MQ-client( ...
- 手把手教你用redis实现一个简单的mq消息队列(java)
众所周知,消息队列是应用系统中重要的组件,主要解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构.目前使用较多的消息队列有 ActiveMQ,RabbitMQ,Zero ...
- Java语言快速实现简单MQ消息队列服务
目录 MQ基础回顾 主要角色 自定义协议 流程顺序 项目构建流程 具体使用流程 代码演示 消息处理中心 Broker 消息处理中心服务 BrokerServer 客户端 MqClient 测试MQ 小 ...
- RocketMQ(消息重发、重复消费、事务、消息模式)
分布式开放消息系统(RocketMQ)的原理与实践 RocketMQ基础:https://github.com/apache/rocketmq/tree/rocketmq-all-4.5.1/docs ...
- IM开发基础知识补课(五):通俗易懂,正确理解并用好MQ消息队列
1.引言 消息是互联网信息的一种表现形式,是人利用计算机进行信息传递的有效载体,比如即时通讯网坛友最熟悉的即时通讯消息就是其具体的表现形式之一. 消息从发送者到接收者的典型传递方式有两种: 1)一种我 ...
- AMQP协议与RabbitMQ、MQ消息队列的应用场景
什么是AMQP? 在异步通讯中,消息不会立刻到达接收方,而是被存放到一个容器中,当满足一定的条件之后,消息会被容器发送给接收方,这个容器即消息队列,而完成这个功能需要双方和容器以及其中的各个组件遵守统 ...
- 不恰当使用线程池处理 MQ 消息引起的故障
现状 业务部门反应网站访问特别慢,负责运维监控的同事说MQ消息队列积压了,中间件的说应用服务器内存占用很高,GC 一直回收不了内存,GC 线程占了近 100% 的 CPU,其他的基本上都在等待,数据库 ...
- activemq消息重发机制[转]
大家知道,JMS规范中,Message消息头接口中有setJMSRedelivered(boolean redelivered)和getJMSRedelivered()方法,用于设置和获取消息的重发标 ...
- java实现MQ消息收发两种方式
定义: 消息队列(MQ)是一种应用程序对应用程序的通信方法.应用程序通过写和检索出入列队的针对应用程序的数据(消息)来通信,而无需专用连接来链接它们.简单理解:蓝牙配对 jar包依赖: <!-- ...
随机推荐
- 根据成绩输出对应的等级(使用if多分支和switch语句分别实现)
根据成绩输出对应的等级,使用if多分支和switch语句分别实现. a) A级 [90,100] b) B级 [80,90) c) C级 [70, ...
- python之type函数
python 的type 函数 的介绍的 下面就是此函数的参数 三个参数的意义 '''type(class_name, base_class_tuple, attribute_dict)cla ...
- macOS10.4后的刻盘新姿势
先sudo -s 输入密码 然后终端拖入createinstallmedia (在macOS Mojave.app显示包内容里面的resources里面的文件复制下来即可) 输入 --volume ...
- Android so注入(inject)和Hook技术学习(二)——Got表hook之导入表hook
全局符号表(GOT表)hook实际是通过解析SO文件,将待hook函数在got表的地址替换为自己函数的入口地址,这样目标进程每次调用待hook函数时,实际上是执行了我们自己的函数. GOT表其实包含了 ...
- Nginx+IIS简单的部署
随着互联网项目用户访问量不断上升,单点web服务器是无法满足大型高并发高负载的业务处理的,为了给web服务器做负载均衡方案,打算采用Nginx搭建负载均衡服务器,把用户请求分配到N个服务器来缓解服务器 ...
- Scala学习(八)练习
Scala中继承&练习 1. 扩展如下的BankAccount类,新类CheckingAccount对每次存款和取款都收取1美元的手续费 class BankAccount ( initial ...
- 自己制作Chrome便携版实现多版本共存
本文只针对Windows下的Chrome浏览器的使用. 有时候我们需要使用老版本Chrome,或者仅仅体验一下最新版. 上古时代有IETester用来测试多个IE版本,和本机的IE不冲突. Chrom ...
- 扒一拔:Java 中的泛型(一)
目录 1 泛型 1.1 为什么需要泛型 1.2 类型参数命名规约 2 泛型的简单实用 2.1 最基本最常用 2.2 简单泛型类 2.2.1 非泛型类 2.2.2 泛型类的定义 2.2.3 泛型类的使用 ...
- Heroku + Node.js + HTTPS
昨天把 biz-to-me 升级到支持 HTTPS 了,为此研究了一下如何让 Heroku 上跑的 Node.js 应用支持 HTTPS.我发现并没有任何文章描述这个具体的流程,只有零碎的信息,所以在 ...
- H5 27-优先级之important
27-优先级之important 我是段落 <!DOCTYPE html> <html lang="en"> <head> <meta c ...