如何处理消费过程中的重复消息?

上一节的内容最后,我们提出了一个思考。如果消息确认响应在网络传输过程中丢失了,那么消息队列的服务端、客户端会认为消息没有被正确传递,从而尝试进行下一次发送。这时候就会产生一些重复消息,那么应该怎么处理这个问题呢?

一. 重复消息一定存在吗?

在MQTT协议中,给出了三种消息传递过程中能够提供的服务质量的三种标准

  1. At most once:至多一次。消息传递时,最多会送达一次消息。也就是说不保证消息的可靠性传输,允许丢失消息的存在。一般都是对消息可靠性要求不太高的监控场景使用,比如饮料销售柜每分钟发送一次心跳。
  2. At least once:至少一次。消息传递时,最少会送达一次消息。也就是说保证了消息的可靠性传输,允许重复消息的存在。
  3. Exactly once:正好一次。消息传递时,只能有一次消息送达。既不允许丢失消息也不允许重复消息。

消息队列也适用于这些标准,大多数的消息队列提供的服务器质量都是At least once,包括RabbitMQ、RocketMQ、Kafka。所以,在适用这些中间件时重复消息时一定会存在的。

二. 如何消除重复消息的影响?

一般处理重复消息的方法是,在消费端,让消费消息的操作具备幂等性。

幂等是数学上的一个概念,它是这样定义的:f(x) = f(f(x))。通俗来讲就是,一个函数使用同样的参数,对它调用一次的结果和多次调用的结果是一样的。

对消费端来说,如果消费操作是幂等操作,那么就算有重复消息传进来,它也会得到相同的结果,从而消除重复消息对系统的影响。即At least once + 幂等消费 = Exactly once。

三. 实现幂等操作的方法

1. 利用数据库唯一性约束实现幂等

如果操作是在数据库insert一条和操作能关联起来的具有唯一性的数据,并根据是否插入成功判断这条消息是否被消费国,就可以实现幂等操作。

这种方式是利用了数据库中的 insert unit 特性

2. 在更新前增加前置判断条件

如果能在数据库操作时添加一个前置条件,如果条件成立就更新,如果条件不成立就不更新,也能实现幂等操作。

这种方法利用了数据库中的 update where 特性

3. 记录并检查记录

前面两种方法都有一定的情景局限性,还有一种通用性最强的方法:记录并检查记录 ,也叫做Token机制或者GUID机制。

具体实现思路是,在发送消息时,给这条消息生成一个全局唯一ID,在消费时先去判断这个ID有没有被消费过,如果没有消费过才进行消费。

?    ?不过这种方式在分布式系统中,很难去实现。首先生成一个唯一的标识就是一件不那么简单的事,方法有很多,但是都不能同时满足简单、高性能、高可用的要求,或多或少会有一些牺牲。其次更麻烦的是,消费时检查、更新数据、更新消费状态这三个操作一定要是原子性的操作,才能保证真正的幂等。

?    ?    ?对于这个问题,我们可以用事务实现,也可以用锁实现,但是无论是分布式事务还是分布式锁都是一个比较难解决的问题。

原文地址:https://www.cnblogs.com/wang-yi-shan/p/11662972.html

时间: 2024-10-31 12:16:47

如何处理消费过程中的重复消息?的相关文章

解决上滑过程中数据重复的问题

问题:最近在做微信小程序的某个项目,手机屏幕上,手指上滑加载更多数据的时候,老是出现重复的数据. 解决方案:状态锁和函数节流. 原理:在向服务器请求数据的时候和接收返回的数据,改变某个变量的状态以及延迟函数的执行. 具体代码: var moreStatus=false; var timeoutId=null; performProcessing: function(){ if(!moreStatus){ moreStatus=true; // 开始向服务器请求数据代码,成功向服务器请求数据之后,

Android ListView滑动过程中图片显示重复错乱闪烁问题解决

转自:http://www.oschina.net/question/221817_121051 主要分析Android ListView滚动过程中图片显示重复.错乱.闪烁的原因及解决方法,顺带提及ListView的缓存机制.1.原因分析ListView item缓存机制:为了使得性能更优,ListView会缓存行item(某行对应的View).ListView通过adapter的getView函数获得每行的item.滑动过程中, a. 如果某行item已经滑出屏幕,若该item不在缓存内,则p

Android ListView滑动过程中图片显示重复错位闪烁问题解决[转载]

转自:here 主要分析Android ListView滚动过程中图片显示重复.错乱.闪烁的原因及解决方法,顺带提及ListView的缓存机制.1.原因分析ListView item缓存机制:为了使得性能更优,ListView会缓存行item(某行对应的View).ListView通过adapter的getView函数获得每行的item.滑动过程中, a. 如果某行item已经滑出屏幕,若该item不在缓存内,则put进缓存,否则更新缓存:b. 获取滑入屏幕的行item之前会先判断缓存中是否有可

MySQL 处理插入过程中的主键唯一键重复值办法

200 ? "200px" : this.width)!important;} --> 介绍 本篇文章主要介绍在插入数据到表中遇到键重复避免插入重复值的处理方法,主要涉及到IGNORE,ON DUPLICATE KEY UPDATE,REPLACE:接下来就分别看看这三种方式的处理办法. IGNORE 使用ignore当插入的值遇到主键(PRIMARY KEY)或者唯一键(UNIQUE KEY)重复时自动忽略重复的记录行,不影响后面的记录行的插入, 创建测试表 CREATE TA

APP store 上架过程中碰到的那些坑&被拒的各种奇葩原因整理&审核指南中文版

苹果官方发布的十大常见被拒原因 1.崩溃次数和Bug数量.苹果要求开发者在将应用提交给App Store之前彻查自己的应用,以尽量避免Bug的存在. 2.链或错误的链接.应用中所有的链接必须是真实且有效的. 3.占位符内容.有占位符内容的应用将无法审核通过. 4.提交的信息不完整.苹果要求开发者提供所有必须在iTunes Connect的应用审查信息区(App Review Information Section)中提交审查时所需要用到的所有完整信息.这是应用审核未通过最常见的原因,占到了14%

Python实现RabbitMQ中6种消息模型

RabbitMQ与Redis对比 ? RabbitMQ是一种比较流行的消息中间件,之前我一直使用redis作为消息中间件,但是生产环境比较推荐RabbitMQ来替代Redis,所以我去查询了一些RabbitMQ的资料.相比于Redis,RabbitMQ优点很多,比如: 具有消息消费确认机制 队列,消息,都可以选择是否持久化,粒度更小.更灵活. 可以实现负载均衡 RabbitMQ应用场景 异步处理:比如用户注册时的确认邮件.短信等交由rabbitMQ进行异步处理 应用解耦:比如收发消息双方可以使用

经测试稳定可用的蓝牙链接通信Demo,记录过程中遇到的问题的思考和解决办法,并整理后给出一个Utils类可以简单调用来实现蓝牙功能

说明:这是本人在蓝牙开发过程中遇到过的问题记录和分析,以及解决办法. 在研究过程中,许多的前人给出的解决方案和思路指导对我相当有帮助,但并非都是可采取的解决方法, 经过本人对这些方法的测试和使用过后,给出自己的理解和解决方案,不一定是正确的,但这些方法的确可以解决问题. 如果有人遇到同样的问题,并且看到我的文章解决,那是我的荣幸. !!!!!!但特别需要说明的是,看的越多,不明白的越多,我的看法可能是完全错误的,这些方法只是暂时解决了我的问题, !!!!!!如果有人发现了我的错误,请私信或评论告

SQL TRACE过程中的事件号详细解释

我们定位数据库性能问题时经常会用到Trace跟踪,下面列举了一下Trace跟踪事件号的含义,方便查看 下表列出了可以在跟踪中添加或删除的事件. 事件号 事件名称 说明 0-9 保留 保留 10 RPC:Completed 在完成了远程过程调用 (RPC) 时发生. 11 RPC:Starting 在启动了 RPC 时发生. 12 SQL:BatchCompleted 在完成了 Transact-SQL 批处理时发生. 13 SQL:BatchStarting 在启动了 Transact-SQL

从输入 URL 到浏览器接收的过程中发生了什么事情

从输入 URL 到浏览器接收的过程中发生了什么事情? 原文:http://www.codeceo.com/article/url-cpu-broswer.html 从触屏到 CPU  首先是「输入 URL」,大部分人的第一反应会是键盘,不过为了与时俱进,这里将介绍触摸屏设备的交互. 触摸屏一种传感器,目前大多是基于电容(Capacitive)来实现的,以前都是直接覆盖在显示屏上的,不过最近出现了 3 种嵌入到显示屏中的技术,第一种是 iPhone 5 的 In-cell,它能减小了 0.5 毫米