如何防止重复提交订单?

news2024/10/3 2:18:53

重复提交原因
其实原因无外乎两种:

一种是由于用户在短时间内多次点击下单按钮,或浏览器刷新按钮导致。
另一种则是由于Nginx或类似于SpringCloud Gateway的网关层,进行超时重试造成的。

常见解决方案
方案一:提交订单按钮置灰

这种解决方案在注册登录的场景下比较常见,当我们点击”发送验证码“按钮的时候,会进行手机短信验证码发送,且按钮就会有一分钟左右的置灰。

有些经验不太丰富的同学,通常会简单粗暴地把这个方案直接照搬过来。

但这种方案只能解决多次点击下单按钮的问题,对于Nginx或类似于SpringCloud Gateway的超时重试所导致的问题是无能为力的。

当然,这种方案也不是真的没有价值。它可以在高并发场景下,从浏览器端去拦住一部分请求,减少后端服务器的处理压力。

说到底,“下单防重”的问题是属于“接口幂等性”的问题范畴。
在这里插入图片描述
接口幂等性是指:以相同的参数,对一个接口进行多次调用,所产生的结果和一次调用是完全相同的。

下面的情况就是幂等的:

student.setName(“张三”);

而这种情况就是非幂等的,因为每次调用,年龄都会增加一岁。

student.increaseAge(1);

现在我们的思路需要切换到幂等性的解决方案来。

同样是幂等性场景,“如何防止重复提交订单” 比 “如何防止订单重复支付” 的解决方案要难一些。

因为,后者在常规情况下,一个订单都是对应一笔支付单,所以orderID可以作为一个幂等性校验、防止订单重复支付的天然神器。

但这个方案在“如何防止重复提交订单”就不适用了,需要其他的解决方案,请继续看下文。

方案二:预生成全局唯一订单号

(1)后端新增一个接口,用于预生成一个“全局唯一订单号”,如:UUID 或 NanoID。

(2)进入创建订单页面时,前端请求该接口,获取该订单号。

(3)在提交订单时,请求参数里要带上这个预生成的“全局唯一订单号”,利用数据库的唯一索引特性,在插入订单记录时,如果该“全局唯一的订单号”重复,记录会插入失败。

btw:该“全局唯一订单号”不能代替数据库主键,在未分库分表场景下,主键还是用数据库自增ID比较好。

优点:彻底解决了重复下单的问题;

缺点:方案复杂,前后端都有开发工作量,还要新增接口,新增字段。

另外,网上还有同学说,要单独弄一个生成“全局唯一订单号”的服务,我觉得还是免了吧,这不是更麻烦了吗?

方案三:前端生成全局唯一订单号

这种方案是在借鉴了“方案二”的基础上,做了一些实现逻辑的简化。

(1)用户进入下页面时,前端程序自己生成一个“全局唯一订单号”。

(2)在提交订单时,请求参数里要带上这个预生成的“全局唯一订单号”,利用数据库的唯一索引特性,在插入订单记录时,如果该“全局唯一的订单号”重复,记录会插入失败。

优点:彻底解决了重复下单的问题,且技术方案做了一定简化;

缺点:前后端仍然都有开发工作量,且需要新增字段;

方案四:从订单业务的本质入手

先跟大家探讨一个概念,什么是订单?

其实,订单就是某个用户用特定的价格购买了某种商品,即:用户和商品的连接。

那么,“如何防止重复提交订单”,其实就是防止在短时间内,用户和商品进行多次连接。弄明白问题本质,接下来我们就着手制定技术方案了。

可以用 ”用户ID + 分隔符 + 商品ID“ 作为唯一标识,让持有相同标识的请求在短时间内不能重复下单,不就可以了吗?而且,Redis不正是做这种解决方案的利器吗?

Redis命令如下:

SET key value NX EX seconds

把”用户ID + 分隔符 + 商品ID“作为Redis key,并把”短时间所对应的秒数“设置为seconds,让它过期自动删除。

这样一来,整体业务步骤如下:

(1)在提交订单时,我们可以把”用户ID + 分隔符 + 商品ID“作为Redis key,并设置过期时间,让它可以到期自动删除。

(2)若Redis命令执行成功,则可以继续走下单的业务逻辑,执行不成功,直接返回给前端”下单失败“就可以了。

优点:彻底解决了重复下单的问题,且在技术方案上,不需要前端参与,不需要添加接口,不需要添加字段;

缺点:综合比较而言,暂无明显缺点,如果硬要找缺点的话,可能强依赖于Redis勉强可以算上吧;

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

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

相关文章

用Blender制作YOLO目标检测器训练数据

推荐:用 NSDT编辑器 快速搭建可编程3D场景 本文将介绍一种非常有吸引力的机器学习训练数据的替代方案,用于为给定的特定应用程序收集数据。 无论应用程序类型如何,这篇博文都旨在向读者展示使用 Blender 等开源资源生成合成数据(S…

一盏茶的功夫帮你彻底搞懂JavaScript异步编程从回调地狱到async/await

🎬 江城开朗的豌豆:个人主页 🔥 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想,就是为了理想的生活 ! 目录 📘 1. 引言 📘 2. 使用方法 📘 3. 实现原理 📘 4. 写到最后…

Linux I/O多路复用 select poll epoll

简介 select函数 poll函数 epoll函数

yolov7车牌识别(12种中文车牌类型)

12种中文车牌类型: 1.单行蓝牌 2.单行黄牌 3.新能源车牌 4.白色警用车牌 5 教练车牌 6 武警车牌 7 双层黄牌 8 双层武警 9 使馆车牌 10 港澳牌车 11 双层农用车牌 12 民航车牌 测试demo: 以yolov7-lite-s 为例: python detect_rec_plate.py --detect_model weigh…

408专题--计算机网络4W字完整版-考研专用

文章目录 前言1.计算机网络体系结构1.1 计算机网络概述1.2 计算机网络的功能1.3 计算机网络的组成1.4 计算机网络分类按照分布范围分类按照交换技术分类按照使用者分类按照传输技术分类按传输介质分类按照拓扑结构分类 1.5 计算机网络的性能指标1.6 计算机网络体系结构1.7 计算…

使用poi-tl循环导出word报表

先看模板和导出的效果 模板 效果 根据模板循环生成表格,每个表格再循环填充数据,也就是两层循环,第一层循环是学生学期信息,第二层循环是学生的成绩数据。 第一个循环 {{?listTable}} {{/}}第二个循环 {{reportList}} 表格…

关于:未同意隐私政策,应用获取ANDROID ID问题

我在提交华为应用时,总是提示【未同意隐私政策,应用获取ANDROID ID个人信息】,但是我已经全部去掉了,后面问了人工客服,反馈了如下信息 调用堆栈 com.unity3d.player.UnityPlayer.nativeRender(Native Method), com.un…

ViewStub

1.作用 1.性能优化&#xff1a; 用到的时候再去加载&#xff0c;不调用加载的话&#xff0c;不会显示 2.使用 1.xml 其中hecate_listview2x为里面加载的布局 <ViewStubandroid:id"id/hecate1_recycler_vs"android:layout_width"match_parent"andr…

python pytorch- TextCNN TextRNN FastText Transfermer (中英文)文本情感分类实战(附数据集,代码皆可运行)

python pytorch- TextCNN TextRNN FastText Transfermer 文本情感分类实战&#xff08;附数据集&#xff0c;代码皆可运行&#xff09; 注&#xff1a;本次实验&#xff0c;主要注重代码实现这些模型&#xff0c;博主的数据集质量较差&#xff0c;模型评估效果并不是十分理想&…

Springboot之AOP的执行顺序

AOP执行顺序验证 项目引入了依赖。自动开启了aop的配置。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>切面上配置Order注解 切面类AopTest1&#xff0c;ord…

华为ICT——第三章图像处理基本任务

目录 1&#xff1a;数字图像处理的层次&#xff1a;&#xff08;处理-分析-理解&#xff09;顺序不能错&#xff1a; 2&#xff1a;图像处理&#xff08;图像处理过程&#xff09;&#xff1a; 3&#xff1a;图像分析&#xff08;特征提取&#xff09;&#xff1a; 4&#x…

vue3前端开发-开发环境安装篇

文章目录 1.安装nvm2.设置安装源为淘宝镜像3.通过nvm安装nodejs4. 安装pnpm4.1 安装pnpm4.2 配置 5.创建vite-vue项目6. vue3demo目录结构7. 扩展插件安装8. 用户代码片段8.1 设置8.2 快速生成代码 1.安装nvm 如果本地已经安装了nodejs&#xff0c;请先卸载。 nvm主要的作用就是…

ES系列十二、ES的scroll Api及分页实例

1.官方api 1.Scroll概念 Version&#xff1a;6.1 英文原文地址&#xff1a;Scroll 当一个搜索请求返回单页结果时&#xff0c;可以使用 scroll API 检索体积大量&#xff08;甚至全部&#xff09;结果&#xff0c;这和在传统数据库中使用游标的方式非常相似。 不要把 scroll 用…

力扣(LeetCode)2578. 最小和分割(C++)

哈希集合 请读者思考&#xff0c;num拆分成num1和num2&#xff0c;要使得num1 num2最小&#xff0c;应满足两条性质&#xff1a; num1和num2位数相同&#xff0c;或最多差一位。num1和num2应按数值从小到大在num中取数。 想到统计num的位数&#xff0c;以实现性质1的需要&a…

JavaSE的常用API学习——字符串相关

目录 一、什么是API 二、String字符串 (一)创建String对象的两种方式 1.直接赋值的内存模型 2.new的内存模型 (二)字符串之间的比较与equals 1.运算符 2.equls()方法 三、StringBuilder的用法 1.StringBuilder的构造方法 2.StringBuilder的常用成员方法 3.小练习&a…

Java中的异常处理方法

在Java开发中&#xff0c;异常处理是必不可少的一部分。良好的异常处理机制可以提高代码的可读性、可靠性&#xff0c;保证程序的稳定性。本文将深度剖析Java中的异常处理机制&#xff0c;并分享一些最佳实践方法&#xff0c;帮助您在实际项目中优雅地处理异常。 一、Java异常…

我用PYQT5做的第一个实用的上位机项目(五)

制作一个动态仪表盘。 具体过程参照前面技术储备阶段的文章&#xff1a; PYQT制作动态时钟-CSDN博客 使用PYQT5简单制作动态仪表盘-CSDN博客 仪表盘由以下部件构成&#xff1a;背景 指针 表盘 进度条&#xff08;设定值&#xff09; 遮罩 设定和显示 其中表盘、 进度条和指…

UWB PDOA定位原理

以下是笔记总结,内容不完全正确 1,什么是PDOA PDOA &#xff0c;英文全称是Phase-Difference-of-Arrival&#xff0c;信号到达相位差 PDOA定位算法的原理如下&#xff1a; UWB基站上放置两个相同且间隔d<λ/2的天线&#xff0c;UWB标签上的信号到达两个天线的相位差就在-180…

实体机 安装 centos

实体机 安装 centos 制作U盘的时候&#xff0c;使用的ultraISO 同样方法一个u盘制作的有问题&#xff0c; 另外一个制作的没有问题。 可能和选择 usb-hdd 或者 usb-hdd 有关 https://mirrors.tuna.tsinghua.edu.cn/centos/7.9.2009/isos/x86_64/ 参考文档&#xff1a; http:…

数据结构的魔法:高级算法优化实战

文章目录 数据结构与算法&#xff1a;基础知识数据结构算法 高级算法优化实战1. 数据缓存2. 哈希表优化3. 算法优化 高级算法优化的挑战结论 &#x1f389;欢迎来到数据结构学习专栏~数据结构的魔法&#xff1a;高级算法优化实战 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;…