如果对方没做幂等!记一次生产订单重复的反思

news2024/11/18 19:41:54

最近公司公司的旧系统中发现了一个bug。业务部门反馈,尽管用户只支付了一年的服务费用,系统却将有效期增加了两年。

原因分析:

到底是什么原因呢?
经过日志分析,发现消息队列(MQ)向第三方服务发送了两次消息。由于第二方服务的接口没有实现幂等性控制,导致了这一重大的bug。

问题反思:

想一想,其实这种问题很简单,怎么会出这种问题呢?

一般来说系统开发中不免会出现不少类似的问题,类似问题的出现并不罕见。一般系统都是从无到有,业务从少到多、早期可能也就几个或者一个研发人员开发出来的,后面升级或重构甚至推倒重来。。。

问题严重性:


这类bug对于系统和业务的影响极大,尤其是涉及金钱的业务,可能会导致严重的财务损失和信誉问题。

在系统开发过程中,正常的服务会确保服务的幂等性,尤其是在涉及金钱交易的业务中。

下面我们就来复盘一下重复消息的产生原因及相应的解决方案:

一、消息重复原因

在消息队列(MQ)系统中,消息重复的情况主要有以下几种原因:

1、生产者重复或重试

生产者代码没有阻止重复请求或处理发送消息后的响应情况,在连接超时等异常情况下,重复发送了相同的消息。当然还有一种情况就是生产者本身设置了重试机制,但重试机制不完善造成重复发送消息。

2、消费者代码问题

消费者在处理消息过程中出现异常,没有正确地手动确认消息,那么该消息会重新投递,导致重复。

3、网络问题

网络延迟或临时断开连接可能导致MQ消费者没有收到确认消息,从而重新消费同一条消息。

4、消息队列集群问题

MQ集群节点之间的状态同步问题,可能导致消息被多个节点重复投递。

当然还有别的一些原因.....

二、消息重复解决方案

针对消息重复的问题,可以从以下几个方面采取解决措施:

1、生产者端解决方案

消息的生产者端的消息溯源还是用户的请求。

第一道防线

首先,前端可以通过禁用按钮、显示加载状态等方式防止用户重复点击提交按钮。禁用按钮是指在用户点击提交按钮后,立即将该按钮禁用,防止再次点击。显示加载状态则是在提交请求后显示加载动画或状态提示,告知用户请求正在处理中。高级一点的做法是使用JavaScript脚本控制按钮的状态,确保用户无法重复提交。不过,前端防重只是第一道防线,因为前端措施容易被绕过,例如通过浏览器开发者工具修改页面元素或捕获和重发请求报文。

第二道防线

如果前端防重措施被绕过,用户可以直接通过程序生成大量请求,此时服务后台需要采取进一步的防重措施。后台可以通过请求频率限制、幂等键、时间戳、哈希值等方式来防止重复请求。请求频率限制是指限制每个用户在一定时间内的请求次数,防止短时间内大量重复请求。幂等键则为每个请求生成唯一的标识符,并在后台存储和检查这些标识符,确保每个请求只处理一次。时间戳和哈希值也是有效的防重手段,通过附加时间戳验证请求的时效性,或对请求内容生成哈希值并检查其唯一性,确保相同内容的请求只处理一次。

第三道防线

在消息的生产者端,也需要采取类似的防重措施以确保消息不被重复发送。例如,在发送消息前生成唯一的消息ID(例如UUID),并将其包含在消息体中。发送消息后,同步等待服务器的回执确认,确保消息只发送一次。此外,可以将消息ID存储在数据库或缓存中,并在发送前检查该ID是否已存在,防止重复发送。当然生产者端一般不会利用这个ID或者叫幂等键来去重,一般会结合消息者端一起来实现。

通过这些多层次的防重措施,能够有效减少消息重复的发生,保障系统的稳定性和可靠性。

2、消费者端解决方案

消息到达消费者端后

第一道防线

消费者端可以使用幂等键来判断请求是否已经处理过。通常情况下,缓存不宜存放过多数据,而重复请求大多数集中在一定时间范围内,因此将幂等键存储在缓存中是一种有效的解决方案。

具体来说,幂等键可以与请求的唯一标识关联,并存储在缓存系统(如Redis或Memcached)中。为每个幂等键设置一个合理的过期时间,可以有效地过滤掉在这个时间范围内的重复请求。通过这种方法,大部分重复请求可以在缓存层被拦截,从而减少对后端服务的压力。

第二道防线

尽管缓存机制可以一定程度上确保幂等性,但是当缓存过期后,可能会再次收到相同的请求。为了更加彻底地解决这个问题,我们需要在数据库层面进一步加强幂等性保证。

当收到请求到达数据库层时,首先检查该请求的幂等键是否已经存在于数据库中。如果存在,则说明该请求已经被处理过,直接返回之前的结果即可;如果不存在,则继续执行请求的业务逻辑。处理完成后,将请求的幂等键及结果持久化到数据库中。当然大多数人还是会选择更简单点的直接把幂等键设置为唯一索引,当报键值重复异常时就忽略些请求直接返回。

3、消息队列层解决方案

  • 利用消息队列中间件的去重功能,如设置成手动ACK、去重插件等。
  • 设置消息的有效时间(TTL),防止过期消息重复投放。
  • 配置死信队列(DLX),存储处理失败的消息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1882376.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

EDI是什么?与ERP有何关系

EDI的发展过程 电子数据交换(Electronic Data Interchange,EDI)是一种通过电子方式传输商业文件的技术。EDI的历史可以追溯到20世纪60年代,当时企业开始使用计算机进行数据处理。最早的EDI系统是为解决大型企业间的信息交换问题而…

【刷题汇总--数字统计、两个数组的交集、点击消除(栈)】

C日常刷题积累 今日刷题汇总 - day0011、数字统计1.1、题目1.2、思路1.3、程序实现 2、两个数组的交集2.1、题目2.2、思路2.3、程序实现 3、点击消除(栈)3.1、题目3.2、思路3.3、程序实现 今日刷题汇总 - day001 1、数字统计 1.1、题目 请统计某个给定范围[L, R]的所有整数中…

智能制造企业CRM系统推荐清单(2024版)

当前,CRM市场呈现出“国际龙头优势逐渐下降,国产CRM奋起直追”的格局。智能制造企业在选型CRM时,如何选择合适的系统是一个需要重视的课题。 在我们之前的文章《一文读懂CRM,2023年30家CRM系统对比(近年最全&#xf…

如何在AWS上使用免费的服务器

要在AWS上免费使用的服务器,你可以按照以下步骤操作: (1)注册AWS账户: 访问AWS官方网站(https://aws.amazon.com/cn/),点击右上角的“完成注册”,按照页面提示填写相关…

经典小游戏(一)C实现——三子棋

switch(input){case 1:printf("三子棋\n");//这里先测试是否会执行成功break;case 0:printf("退出游戏\n");break;default :printf("选择错误,请重新选择!\n");break;}}while(input);//直到输入的结果为假,循环才会结束} …

基于FreeRTOS+STM32CubeMX+LCD1602+MCP23S09(SPI接口)的I/O扩展器Proteus仿真

一、仿真原理图: 二、运行效果: 三、STM32CubeMX配置: 1)、GPIO配置: 2)、SPI配置: 四、部分软件: 1)、主函数: /* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : mai…

游戏AI的创造思路-技术基础-关于艾宾浩斯遗忘曲线的迷思

对于艾宾浩斯遗忘曲线和函数,我一直都有小小的迷思,总想实验下用艾宾浩斯函数来替换sigmoid函数作为激活函数,打造更接近人类的AI算法,这篇文章旨在讨论下 目录 3.10. 艾宾浩斯曲线 3.10.1. 定义 3.10.1.1. 曲线计算公式 3.10…

想用AI高端算力训练模型?试试英智BayStone平台

随着生成式人工智能的迅猛增长,各大公司纷纷推出强大的 AI产品以提升自身核心竞争力,对于依赖基础模型进行推理训练,同时需要高级基础设施的人工智能初创企业,急需使用高端智算算力来加速模型训练与产品研发创新。 算力是否充足&…

测试接口的完整流程

背景 今天睿哥给我布置了一个任务,叫我学习一下如何测试接口。 然后我就上网搜索去了解了一下,看看测试接口是什么。看了很久之后,我大概对接口测试有了一定的理解。 通俗来说,接口测试就是使用某种工具模拟客户端发送http请求…

Github 上 Star 数最多的大模型应用基础服务 Dify 深度解读(一)

背景介绍 接触过大模型应用开发的研发同学应该都或多或少地听过 Dify 这个大模型应用基础服务,这个项目自从 2023 年上线以来,截止目前(2024-6)已经获得了 35k 多的 star,是目前大模型应用基础服务中最热门的项目之一…

HEC-HMS水文模型教程

原文链接:HEC-HMS水文模型教程https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247607904&idx5&sn1a210328a3fc8f941b433674d8fe2c85&chksmfa826787cdf5ee91d01b6981ebd89deac3e350d747d0fec45ce2ef75d7cb8009341c6f55114d&token90645021…

智能驾驶系列报告:特斯拉智能驾驶方案简剖

不同于绝大多数国内车企在自动驾驶上采取多传感器融合方案,特斯拉FSD在发展初期就摒弃激光雷达、且不配备高清地图,成为在感知层以摄像头为核心的纯视觉解决方案代表;其依靠车身搭载的摄像头来捕捉周围的环境信息,并经过算法及神经网络模型处…

JOSEF约瑟 YHSJ-J打滑开关 使用带速0.3-5.0m/s

产品概述: YHSJ-J打滑开关是一种智能型超速打滑检测器,采用非接触式监测方式,自动采集设备正常运行时的转速,并通过监测转速变化量和相关控制参数进行比较,以判断是否存在打滑现象。 该产品已广泛应用于输送系统中&…

【智慧水利数字孪生解决方案】

在2024年全国水利工作重点会议上,水利部部长李国英发表重要讲话,强调:大力推进数字孪生水利建设。坚持需求牵引、应用至上、数字赋能、提升能力,加快构建数字孪生水利体系,为水利治理管理提供前瞻性、科学性、精准性、…

“论云上自动化运维及其应用”写作框架,软考高级论文,系统架构设计师论文

论文真题 云上自动化运维是传统IT运维和DevOps的延伸,通过云原生架构实现运维的再进化。云上自动化运维可以有效帮助企业降低IT运维成本,提升系统的灵活度,以及系统的交付速度,增强系统的可靠性,构建更加安全、可信、…

明星中药企业系列洞察(九)一手好牌打的稀烂!近500年老字号锁定退市,太安堂为何“塌房”了?

近日,太安堂发布公告称,公司已收到深交所下发的《关于广东太安堂药业股份有限公司股票终止上市的决定》,深交所决定终止公司股票上市,预计其最后交易日期为7月4日。太安堂曾作为国内知名的中成药上市公司之一,是国家级…

动捕系统如何解决“超出捕捉范围”的挑战

惯性运动捕捉系统改变了我们捕捉运动的方式,使艺术家、创作者和独立工作室能够摆脱动捕实验室和复杂设置的限制。通过身体上的传感器和无线连接,动捕演员可以自由移动和并作出各种高难度动作。然而具有高自由度的惯性动捕系统,经常面临着超出…

深入解析 androidx.databinding.BaseObservable

在现代 Android 开发中,数据绑定 (Data Binding) 是一个重要的技术,它简化了 UI 和数据之间的交互。在数据绑定框架中,androidx.databinding.BaseObservable 是一个关键类,用于实现可观察的数据模型。本文将详细介绍 BaseObservab…

雨量气象站:野外监测的得力助手

在广阔无垠的大自然中,雨量、风力、风向、温湿度以及大气压力等气象数据对于各种应用场景都至关重要。特别是在野外、森林防火、山洪监测等无市电供电的场合,一款高效可靠的监测设备更是不可或缺。雨量气象站正是为了满足这些需求而诞生的户外专用监测站…

昇思25天学习打卡营第8天|模型训练

昇思25天学习打卡营第8天|模型训练 前言模型训练构建数据集定义神经网络模型定义超参、损失函数和优化器超参损失函数优化器 训练与评估 个人任务打卡(读者请忽略)个人理解与总结 前言 非常感谢华为昇思大模型平台和CSDN邀请体验昇思大模型!从…