如何防止重复下单

文章目录

  • 一:重复下单与幂等性问题
  • 二:如何解决重复下单问题
  • 三:总结

一:重复下单与幂等性问题

用户在下单页面进行下单时,由于用户点击下单按钮 多次 、或者 重试策略导致在订单服务中接收到了 两次同样 的下单请求

什么情况下会重复下单

  1. 用户短时间内多次点击下单按钮
  2. 超时重试
  3. 用户APP强退/闪退之后重新下单

重复下单问题,本质上,就是下单操作的幂等性问题,说到底,就是接口幂等性。

二:如何解决重复下单问题

方案一:提交订单按钮置灰
浏览器端去拦住一部分请求,减少后端服务器的处理压力,达到过滤流量的效果。
方案一优点:简单。基本可以防止重复点击提交按钮造成的重复提交问题。
方案一缺点:前进后退操作,或者F5刷新页面等问题并不能得到解决。因为服务端这里没有加限制

方案二:请求唯一ID+数据库唯一索引约束(数据库层面做幂等)

  1. 当用户进入订单提交界面的时候,调用后端获取请求唯一ID,并将唯一ID值埋点在页面里面。
  2. 当用户点击提交按钮时,后端检查这个唯一ID是否用过,如果没有用过,继续后续逻辑;如果用过,就提示重复提交。
  3. 最关键的一步操作,就是把这个唯一ID 存入业务表中,同时设置这个字段为唯一索引类型,从数据库层面做防止重复提交

缺点:DB层面约束,并发量低

方案三:redis分布式锁 + token 推荐

  1. 用户点击提交订单按钮,服务端接受到请求后,通过规则计算出本次请求唯一ID值
    • 接口唯一ID:应用名+接口名+方法名+请求参数签名(请求header、body参数,取SHA1值)
  2. 使用redis的分布式锁服务,对请求 ID 在限定的时间内尝试进行加锁,如果加锁成功,继续后续流程;如果加锁失败,说明服务正在处理,请勿重复提交。
  3. 最后一步,如果加锁成功后,需要将锁手动释放掉,以免再次请求时,提示同样的信息。

思考:同一个用户可能就是想买两次相同的产品,可能说先买了一个,刚买完发现需要两个,再买一个同一个产品,所以这时候我们设计不能不让用户买,这种情况就是说能不能对唯一ID设计上来区分这次请求,如果说不能区分,那在我们业务上redis分布式锁的时间范围这要去设计准确点,比如说一次下单到支付需要多长时间,锁的时间设置为比这个时间稍大些,不能时间太长,这样用户第二次购买发现不让重复操作。当然前面只是一种思路,还比如能不能经过判断后唯一ID相同,但是不知道用户是不是想重复购买,这时候可以给用户提示:发现购买相同,是否继续,继续那就放行,不继续就拦截。

代码实现思路:使用AOP实现对业务token的无侵入生成
可以定义注解,在生成订单的方法上加该注解,AOP的逻辑就是生成唯一token,然后加锁,看加锁能不能成功,成功则放行执行后续逻辑,失败则表示重复下单,拦截。


万能方案
一锁二判三更新
一锁:先加锁,可以加分布式锁、悲观锁都可以,但是一定是一个互斥锁
二判:进行幂等性判断,可以基于状态机业务流水表数据库唯一索引等,进行重复操作的判断。
三更新:对数据进行更新,将数据进行持久化。

三:总结

防止重复下单,本质上就是先做重复判断,然后服务端做好幂等性控制,结合实际业务场景选择相应的方案。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

设计模式之模板方法模式详解(下)

3)钩子方法的使用 1.概述 钩子方法的引入使得子类可以控制父类的行为。 2.结构图 3.代码实现 将公共方法和框架代码放在抽象父类中 abstract class DataViewer {//抽象方法:获取数据public abstract void GetData();//具体方法:转换数据…

每日一题 — 最小覆盖子串

76. 最小覆盖子串 - 力扣(LeetCode) 解法一:暴力遍历哈希表 解法二:滑动窗口哈希表 定义left和right初始化为零,固定left,先向右遍历right,放到哈希表中这个时候我们需要统计有效字符的个数&…

深入挖掘C语言 ---- 文件操作

目录 1. 文件的打开和关闭1.1 流和标准流1.1.1流1.1.2标准流 1.2 文件指针1.3 文件的打开和关闭 2. 顺序读写3. 随机读写3.1 fseek3.2 ftell3.3 rewind 4. 读取结束判定 正文开始 1. 文件的打开和关闭 1.1 流和标准流 1.1.1流 我们程序的数据需要输出到各种外部设备, 也需要…

Leetcode算法训练日记 | day30

一、重新安排行程 1.题目 Leetcode:第 332 题 给你一份航线列表 tickets ,其中 tickets[i] [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。 所有这些机票都属于一个从 JFK(肯尼迪国际机场)出发…

java算法day2

螺旋矩阵搜索插入位置查找元素第一个位置和最后一个位置 螺旋矩阵 解法:模拟,核心在于你怎么转,还有就是处理边界,边界如何收缩,什么时候停止旋转。最内圈的时候怎么处理。 通过上图的模拟来解决这个问题:…

数据库锁等待排查方法、命令行安装数据库及授权文件更新

欢迎关注“数据库运维之道”公众号,一起学习数据库技术! 本期将为大家分享“数据库锁等待排查方法、命令行安装数据库及授权文件更新”的运维技能。 关键词:锁等待、V$LOCK、V$TRXWAIT、死锁、锁超时、命令行部署达梦、授权文件更新 当用户反馈执行SQL语…

1985-2022年各地级市专利申请数据

1985-2022年各地级市专利申请数据 1、时间:1985-2022年 2、指标:行政区划代码、地区、省份、城市、年份、发明公布(申请数)、其中:获得授权、外观设计申请量、实用新型申请量 3、来源:国家知识产权局 4…

【Java】简单实现图书管理系统

前言 在本篇博客当中,我们会使用Java基础语法来简单实现一个图书管理系统,主要用到的知识为:封装、多态、继承、接口等等,并不会使用数据库来存储数据,请注意 需求 1. 要求设置管理员和普通用户两种身份&#xff0c…

【深度学习实战(9)】三种保存和加载模型的方式

一、state_dict方式(推荐) torch.save(model.state_dict(), PATH)model YourModel() model.load_state_dict(torch.load(PATH)) model.eval()记住一定要使用model.eval()来固定dropout和归一化层,否则每次推理会生成不同的结果。 二、整个…

实验室三大常用仪器3---交流毫伏表的使用方法(笔记)

目录 函数信号发生器、示波器、交流毫伏表如果连接 交流毫伏表的使用方法 测量值的读数问题 实验室三大常用仪器1---示波器的基本使用方法(笔记)-CSDN博客 实验室三大常用仪器2---函数信号发生器的基本使用方法(笔记)-CSDN博客…

C#自定义窗体更换皮肤的方法:创建特殊窗体

目录 1.窗体更换皮肤 2.实例 (1)图片资源管理器Resources.Designer.cs设计 (2)Form1.Designer.cs设计 (3)Form1.cs设计 (4) 生成效果 (5)一个遗憾 1.窗…

Git常见命令行操作和IDEA图形化界面操作

设置Git用户名和标签 在安装完Git以后需要设置用户和签名,至于为什么要设置用户签名可以看一下这篇文章【学了就忘】Git基础 — 11.配置Git用户签名说明 - 简书 (jianshu.com) 基本语法: git config --global user.name 用户名 git config --global u…

SpringBoot项目创建及简单使用

目录 一.SpringBoot项目 1.1SpringBoot的介绍 1.2SpringBoot优点 二.SpringBoot项目的创建 三.注意点 一.SpringBoot项目 1.1SpringBoot的介绍 Spring是为了简化Java程序而开发的,那么SpringBoot则是为了简化Spring程序的。 Spring 框架: Spring…

ARM之栈与方法

ARM之栈与方法 计算机中的栈是一种线性表,它被限定只能在一端进行插入和删除操作(先进后出)。通常将可以插入和删除操作的一端称为栈顶,相对的一端为栈底。 通常栈有递增堆栈(向高地址方向生长)、递减堆栈…

鸿蒙OpenHarmony【搭建Ubuntu环境】

搭建Ubuntu环境 在嵌入式开发中,很多开发者习惯于使用Windows进行代码的编辑,比如使用Windows的Visual Studio Code进行OpenHarmony代码的开发。但当前阶段,大部分的开发板源码还不支持在Windows环境下进行编译,如Hi3861、Hi3516…

Day37 IO流的操作

Day37 IO流的操作 文章目录 Day37 IO流的操作Java的文件拷贝利用 文件字节输出流 向文件写入数据利用 文件字节输入流 读取文件里的数据利用 带缓冲区的字节输出流 向文件写入数据利用 带有缓冲区的字节输入流 读取文件里的数据利用 字符输出转换流 向文件写入数据利用 字符输入…

Java全套智慧校园系统源码springboot+elmentui +Quartz可视化校园管理平台系统源码 建设智慧校园的5大关键技术

Java全套智慧校园系统源码springbootelmentui Quartz可视化校园管理平台系统源码 建设智慧校园的5大关键技术 智慧校园指的是以物联网为基础的智慧化的校园工作、学习和生活一体化环境,这个一体化环境以各种应用服务系统为载体,将教学、科研、管理和校园…

豆瓣影评信息爬取 (爬虫)

代码块: from lxml import etree import requestsheaders{User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0 }url_list[] for i in range(0,5):i*20urlsf"https:…

day02-新增员工

day01 新增员工业务逻辑整理 EmployeeController.java PostMappingApiOperation("新增员工")public Result save(RequestBody EmployeeDTO employeeDTO){System.out.println("当前线程的ID:" Thread.currentThread().getId());log.info("新增员工&a…

[leetcode] 56. 合并区间

文章目录 题目描述解题方法排序java代码复杂度分析 题目描述 以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区…
最新文章