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

06 | 如何处理消费过程中的重复消息? 在消息传递过程中,如果出现传递失败的情况,发送方会执行重试,重试的过程中就有可能会产生重复的消息。对使用消息队列的业务系统来说,如果没有对重复消息进行处理,就有可能会导致系统的数据出现错误。 阅读详情

在消息传递过程中,出现传递失败情况,发送方会重试,重试会导致产生重复消息。

因此使用消息队列的业务系统若没对重复消息处理,就可能会导致系统数据出错。

比如消费订单消息,统计下单金额的服务,就会出现重复统计,导致统计结果出错。

可能有人会问,如果消息队列本身能保证消息不重复,应用程序实现不就简单了。那有消息队列能保证这点么?

消息重复的情况必然存在

在MQTT协议中,给出了三种传递消息时能够提供的服务质量标准。质量从低到高,

At most once:最多一次,无消息可靠性,允许丢消息。一般对消息可靠性要求不高的监控场景使用。比如每分钟上报一次机房温度。

At least once:至少一次,不允许丢消息。但允许少量重复出现。

Exactly once:恰好一次,消息不允许丢,也不允许重复,最高等级。

对多有消息队列都是适用的,这个服务质量标准不仅适用于MQTT。现在常用绝大部分消息队列提供的服务质量都是At least once,包括 rabbitmq, rocketmq, kafka。也就是消息队列很难保证消息不重复。

注意,kafka的exactly once是它的事务中支持的一个特性。

既然按照标准大部分消息队列无法保证消息不重复,就需要消费代码能够接受消息是可能重复的这一个现状,然后通过一些方法来消除重复消息对业务的影响。

用幂等性解决重复消费问题

一般解决重复消息的办法是,在消费端的消费消息的操作具备幂等性。

Idempotence: 如果函数f(x) 满足 f(x) = f(f(x)), f(x)满足幂等性。

这个概念拓展到计算机领域,被用来描述一个操作、方法或者服务。

一个幂等的方法,使用同样的参数,对它进行多次调用和一次调用,对系统产生的影响是一样的。

比如设置某个账户余额=100元是幂等的,但是设置某个账户余额+100元不是。执行多次和一次对系统的影响是不一样的。

从对系统结果来说:At least once + 幂等消费 = Exactly once。

设计幂等操作的方法

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

刚刚提及的不具备幂等特性的转账的例子:将账户X的余额+100,改为限定每个账单每个账户只可以执行一次变更操作。

具体在分布式系统中上述限制方法较多:

方法一:建一张流水表,表有3个字段:转账单ID、账户ID、变更金额。uniq key(转账单ID、账户ID)

不仅关系DB,只要支持INSERT IF NOT EXIST 语义的存储系统都可以实现。比如Redis的SETNX命令。

2. 为更新的数据设置前置条件

以前述账户余额+100为例,改为当账户余额为500的时候+100,就保证了幂等性。

有时候更新字段并不是数字,则可以加一个版本号字段,同时对版本号进行判断和递增。

3. 记录并检查操作

通用性最强,适用范围最广的实现幂等性的方法。

在执行数据更新操作前,先检查一下是否执行过这个更新操作。

具体的实现方法是,在发送消息时,每条消息执行全局唯一ID,消费时,先根据这个ID检查这条消息,没被消费过,再执行数据更新,再讲消息状态置为已消费。

分布式系统中,要做到这点不简单。

1. 全局唯一ID的生成

2. 检查消费状态,更新数据,更新消费状态,三个操作的原子性;

第一个点,在分布式系统中,很难找到一个简单、高可用、高性能的实现方案。

第二个点, 在分布式系统中,可以用分布式事务或者分布式锁,但都不是容易的事。

小结

主要介绍通过幂等来解决消息重复消费的问题。

实现幂等的方案主要有,利用数据库的唯一性约束,为数据更新设置一次性的前置条件,记录并检查操作。

这些实现幂等的方法,不仅可以用于重复消息的问题,也适用于,

在其他场景中来解决重复请求或者重复调用的问题。

比如HTTP服务;

APP或前端重复提交表单;

也可以将微服务设计成幂等,解决RPC框架自动重试导致的重复调用问题;

思考

为什么大部分消息队列都只是 at least once,而不是excatly once的实现呢?

Qt5.14.2+VS2017开发环境搭建全流程(含插件配置与项目测试) 本文详细介绍了Qt5.14.2与VS2017开发环境的完整搭建流程,包括软件安装、插件配置、环境变量设置以及项目测试。特别针对实际开发中常见的配置问题提供解决方案,帮助C++开发者快速搭建高效的Qt开发环境。 阅读详情

相关推荐

2026 最新实战教程:AI 重构开发全流程(从需求→上线→运维)

1)做什么系统2)技术栈3)功能模块4)部署要求plaintext我要做一个:待办事项(Todo)全栈应用技术栈:前端:React + TypeScript + Tailwind后端:Node.js + Express + MongoDB部署:Docker + 本地运行(后续可上云)功能:- 增删改查任务- 任务状态切换(完成/未完成)- 简单错误处理请按企业级标准生成:架构设计 + 全部代码 + 接口文档 + 启动命令。

qq_35779316的博客 1681

如何防止消息的重复消费_Spring Cloud Stream如何处理消息重复消费?

最近收到好几个类似的问题:使用Spring Cloud Stream操作RabbitMQ或Kafka的时候,出现消息重复消费的问题。通过沟通与排查下来主要还是用户对消费组的认识不够。其实,在之前的博文以及《Spring Cloud微服务实战》一书中都有提到关于消费组的概念以及作用。那么什么是消费组呢?为什么要用消费组?它解决什么问题呢?摘录一段之前博文的内容,来解答这些疑问:通常在生产环境,我们的...

weixin_36362920的博客 551

pyinstaller+scrapy打包出现错误:OSError: could not get source code

错误如下: Traceback (most recent call last): File "scrapy\utils\defer.py", line 55, in mustbe_deferred File "scrapy\core\spidermw.py", line 60, in process_spider_input File "scrapy\core\scraper.py", line 152, in call_spider File "scrapy\utils\misc.py

kin的博客 1759

mq要如何处理消息丢失、重复消费?

如果要你实现一个支付宝向余额宝转账的功能,比如:账户a从支付宝转出5000余额宝转入5000,该怎么做呢? 可能有些人会说,这还不简单,直接上图 支付宝先给账户a减5000,调用余额宝的接口给余额宝的账号b加5000。 用这种方式正常情况下是可以的,如果出现以下问题该怎么办呢? 调用余额宝api时网络失败了 调用余额宝api时网络超时了 如果余额宝api业务逻辑比较复杂,耗时比较长,用户需要长时间的等待才有结果,用户体验不好 有人说:如果调用余额宝api时网络失败了,对接口进行重试不就可以解

风起尘落的博客 2045

AutoCAD提示找不到acdb24.dll、AcGe24.dll、AcPal.dll、AcUt.dll怎么办?

在我们安装了AutoCAD 2023版本以后,打开CAD,可能会出现dll文件丢失的情况,如下所示:1、由于找不到acdb24.dll,无法继续执行代码。重新安装程序可能解决此问题。2、由于找不到AcGe24.dll,无法继续执行代码。重新安装程序可能解决此问题。3、由于找不到AcPal.dll,无法继续执行代码。重新安装程序可能解决此问题。4、由于找不到AcUt.dll,无法继续执行代码。重新安装程序可能解决此问题。遇到AutoCAD启动系统错误,由于找不到dll文件该怎么处理呢?

huoxu369的博客 1万+

UE4_UE5 自定义简单水材质(UE材质图表大全1)

首先是材质的颜色节点、粗糙度节点、透明度节点。(1/2/3/4键+右键空白处,可创建一/二/三/四维节点)接着是两个法线波动节点的叠加。最后是折射节点,将fresnel菲涅尔节点连接到材质结果节点的折射输入端。到这里,你基本已经实现了一个波纹流动的水材质。后续我会更新加上海面浪花的水面材质,可以到我的专栏中寻找。有问题随时私信沟通,加油❤。

shanlinhan的博客 1983

rocketmq 顺序消费_RocketMQ 消息中间件

RocketMQ 特点: RocketMQ 是阿里巴巴在2012年开源的分布式消息中间件,目前已经捐赠给 Apache 软件基金会,并于2017年9月25日成为 Apache 的顶级项目。作为经历过多次阿里巴巴双十一这种“超级工程”的洗礼并有稳定出色表现的国产中间件,以其高性能、低延时和高可靠等特性近年来已经也被越来越多的国内企业使用。其主要特点有:灵活可扩展性RocketMQ 天然支持集群,其核...

weixin_39847099的博客 465

基于verilog实现AXI4协议接口读写功能

AXI4是ARM公司推出的第四代AMBA总线协议,专为高带宽、低延迟的片上通信设计,广泛应用于FPGA、处理器及DSP等复杂系统,AXI4包含三中形态,分别为AXI4:标准版本,支持高带宽内存映射通信。AXI4-Lite:简化版,用于寄存器等简单设备的轻量级访问。AXI4-Stream:无地址协议,适用于高速数据流传输(如视频、音频)。本文章主要介绍AXI4协议的代码实现1. 写地址通道定义2. 写数据通道定义3. 写响应通道定义4. 读地址通道定义5. 读数据通道定义。

junpingc的博客 628

如何保证消息不被重复消费?

在消费消息时,首先从消息的properties中获取messageId属性,并使用isMessageProcessed()方法查询该消息是否已经被处理过。这是因为RabbitMQ是一个消息的投递机制,只有在消费者确认了消息已经被处理后,才会从消息队列中删除该消息。在消费下一条消息时,先查询是否已经消费过该消息,如果已经消费过,则不再处理。在Java中,可以使用消息队列来实现消息的异步处理,其中常用的消息队列有 RabbitMQ、ActiveMQ、Kafka 等。1.消息队列提供的幂等性机制。

zy1992As的博客 5398

保姆级教程:用YOLOv8/9/10搞定仪表盘指针识别,附完整数据集和Python环境配置

本文提供了一份基于YOLOv8/v9/v10的仪表盘指针检测全流程指南,涵盖环境配置、数据集构建、模型选型、训练调优和部署落地等关键步骤。通过详细的代码示例和实战经验,帮助开发者高效解决工业视觉中的仪表盘检测难题,特别适合电力巡检、智能监控等应用场景。

weixin_29031057的博客 1335

系统学习消息队列分享(七) 如何处理消费过程中的重复消息?

在消息传递过程中,如果出现传递失败的情况,发送方会执行重试,重试的过程中就有可能会产生重复的消息。对使用消息队列的业务系统来说,如果没有对重复消息进行处理,就有可能会导致系统的数据出现错误。 比如说,一个消费订单消息,统计下单金额的微服务,如果没有正确处理重复消息,那就会出现重复统计,导致统计结果错误。 你可能会问,如果消息队列本身能保证消息不重复,那应用程序的实现不就简单了?那有没...

weixin_30586085的博客 558

软件测试高频面试题 2026 最新整理(功能 + 自动化)

本文系统整理了2026年软件测试面试高频题目及参考答案,涵盖功能测试、自动化测试及新兴热点领域。功能测试部分包含测试基础概念、用例设计方法、缺陷管理流程等10个必背题;自动化测试部分详细解析工具选择、元素定位、框架搭建等10个热门考点;新增章节聚焦AI测试、安全测试、性能指标等5个前沿话题。参考答案均采用结构化表述,包含定义、区别、适用场景等关键要素,并强调结合项目经验作答。文末提供2026版面试技巧,建议采用"结论-分点-总结"的回答逻辑,重点展现问题解决能力和技术前瞻性。

SmallBull的博客 1958

消息队列_06(如何处理消息消费过程中的重复消息)

如何处理消息消费过程中的重复消息 1.MQTT协议,三种传递消息是的服务质量标准 At most once:至多一次。消息在传递时,最多会被送达一次。允许丢消息 At least once:至少一次。消息在传递时,至少会被传达一次。不允许丢消息,但允许有少量重复消息 Exactly once:恰好一次。消息在传递时,只会被送达一次,不允许丢失也不允许重复。 这些服务质量标准对所有的消息队列都是适...

qq_21486655的博客 396

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

RocketMQ~重复消息、消息堆积、回溯消费、如何防止消息不丢失

我们需要给我们的消费者实现幂等解决重复消息,也就是对同一个消息的处理结果,执行多少次都不变。这个还是需要结合具体的业务的。你可以使用写入Redis来保证,因为Redis 的 key 和 value 就是天然支持幕等的。当然还有使用用数据库插入法,基于数据库的唯一键来保证重复数据不会被插入多条。不过最主要的还是需要,你要知道你的消息消费是否是完全不可重复消费、还是可以忍受重复消费的,然后再选择强校验和弱校验的方式。

Shangxingya的博客 1730

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

科普文:软件架构设计之【消息队列中的关键问题:消息丢失、顺序消费、消息积压与重复消费】

在分布式系统中,消息队列扮演着至关重要的角色,它解耦了系统组件,提高了系统的可扩展性和可靠性。然而,在使用消息队列时,我们经常会遇到一些问题,如消息丢失、顺序消费、消息积压和重复消费。本文将深入探讨这些问题的原因,并提供相应的解决方案。

为无为,事无事,味无味。 1527

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

科普文:软件架构设计之【实战解决消息队列中的关键问题:消息丢失、顺序消费、消息积压与重复消费】

一般而言,一个新的系统刚刚上线,各方面都不太稳定,需要一个磨合期,这个时候,特别需要监控到你的系统中是否有消息丢失的情况。如果是 IT 基础设施比较完善的公司,一般都有分布式链路追踪系统,使用类似的追踪系统可以很方便地追踪每一条消息。可以利用消息队列的有序性来验证是否有消息丢失。原理非常简单,在 Producer 端,我们给每个发出的消息附加一个连续递增的序号,然后在 Consumer 端来检查这个序号的连续性。

为无为,事无事,味无味。 1138

面试题:如何保证消息不被重复消费?如何保证消息消费的幂等性?

Kafka 实际上有个 offset 的概念,就是每个消息写进去,都有一个 offset,代表消息的序号,然后 consumer 消费了数据之后,每隔一段时间(定时定期),会把自己消费过的消息的 offset 提交一下,表示“我已经消费过了,下次我要是重启啥的,你就让我继续从上次消费到的 offset 来继续消费吧”。能不能避免重复消费?幂等性,通俗点说,就一个数据,或者一个请求,给你重复来多次,你得确保对应的数据是不会改变的,不能出错。当然,如何保证 MQ 的消费是幂等性的,需要结合具体的业务来看。

Java开发工程师,专注微服务、分布式系统,部署运维,分享实战经验和源码解析。 476

Java面试八股之如何保证消息队列中消息不重复消费

结合上述方法,可以根据具体的应用场景选择合适的策略来避免消息的重复消费。如果需要具体的编程语言或框架的示例,请告诉我你正在使用的环境和技术栈,我可以给出更具体的建议。设计消息处理逻辑使其具有幂等性,即无论消息被消费多少次,其产生的效果都是一样的。例如,在数据库操作中可以使用唯一键约束来防止重复记录的插入。可以通过维护一个外部的数据结构(如数据库表或缓存),用来记录哪些消息已经被成功处理过,从而避免重复处理相同的消息。在某些情况下,可以通过消息ID或者消息内容来检查是否已经处理过该消息,以此来实现去重。

u012151345的博客 524

消息队列重复消费,少发,多发问题

希望这些信息对你有所帮助!- **幂等性处理**:消费者在处理消息时需要设计幂等性逻辑,即使消息被重复发送,也只处理一次。4. **幂等性设计**:消费者在处理消息时检查是否已经处理过相同的消息,例如通过数据库中的唯一约束来避免重复插入数据。- **消息持久化**:将消息持久化到磁盘,确保即使在消息队列服务重启的情况下,未处理的消息也不会丢失。- **消息队列的同步机制**:确保消息队列在发送消息前等待必要的确认信号,避免重复发送。2. **消息持久化**:设置消息为持久化模式,确保消息存储到磁盘。

weixin_43803780的博客 399

面试官:给我一个避免消息重复消费的解决方案?

‍点击上方☝码猿技术专栏轻松关注,设为星标!及时获取有趣有料的技术原文链接:https://jaskey.github.io/blog/2020/06/08/rocketmq-messa...

码猿技术专栏 317

core net 消费kafka_消息队列(三):如何保证消息不被重复消费?

作者:王博博链接:https://blog.nowcoder.net/n/98195d2b8c294ee89d7b22fe06f4d151来源:牛客网说一说可能会有哪些重复消费的问题。首先,比如 RabbitMQ、RocketMQ、Kafka,都有可能会出现消息重复消费的问题,正常。因为这问题通常不是 MQ 自己保证的,是由我们开发来保证的。挑一个 Kafka 来举个例子,说说怎么重复消费吧。Ka...

weixin_42499201的博客 167

RabbitMq幂等性问题(消息重复消费)思路

重复投递:生产在往MQ发送消息时,MQ收到消息并持久化到本地后,进行发布确认告诉生产者,消息已经被持久化的过程中出现网络中断,生产者没有收到消息发布确认的消息,故而重新发送一条消息重复消费:消费者在消费 MQ 中的消息时,MQ 已把消息发送给消费者,消费者在给 MQ 返回 ack 时网络中断, 故 MQ 未收到确认信息,该条消息会重新发给其他的消费者,或者在网络重连后再次发送给该消费者,但实际上该消费者已成功消费了该条消息,造成消费者消费了重复的消息。

南风北街 245

图解RocketMQ之消费者如何进行消息重试

大家好,我是苍何。在上一篇[[图解RocketMQ之生产者如何进行消息重试]]中分析了当生产者发送消息失败的时候,RocketMQ 是如何进行重试的。最后留了一个问题,生产端的消息是重试 hold 住了,但如果消费者出现异常,消费某一条消息失败,这时候 RocketMQ 会怎么处理呢?这还是很普遍的场景,试想一下如果订单系统发了个消息出去,库存系统消费这条消息失败,那会出现一个什么奇葩的现象呢?就是你明明下了单买了一包辣条,结果迟迟收不到货,一查人说你的辣条订单压根没出库。

一个成长中的程序员,期待用技术的眼光生活 1048
上一篇: 05 | 如何保证消息不丢失
下一篇: 07 | 消息积压了该如何处理?
vectorX
博客等级 码龄11年 37粉丝 21原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值