得物面试:10wqps高并发,如何防止重复下单?

尼恩说在前面

在40岁老架构师 尼恩的读者交流群(50+)中,最近有小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格,遇到很多很重要的面试题:

10wqps高并发,如何防止重复提交/支付订单?

10wqps高并发,如何防止重复下单?

10wqps高并发,如何防止重复支付?

10wqps高并发,如何解决重复操作问题?

最近有小伙伴在面试得物,又遇到了这个的面试题。小伙伴支支吾吾的说了几句,面试官不满意,面试挂了。

所以,尼恩给大家做一下系统化、体系化的梳理,使得大家内力猛增,可以充分展示一下大家雄厚的 “技术肌肉”,让面试官爱到 “不能自已、口水直流”,然后实现”offer直提”。

当然,这道面试题,以及参考答案,也会收入咱们的 《尼恩Java面试宝典PDF》V171版本,供后面的小伙伴参考,提升大家的 3高 架构、设计、开发水平。

最新《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》的PDF,请关注本公众号【技术自由圈】获取,回复:领电子书

基础知识:电商订单支付核心流程

首先,来看看 订单支付的业务流程和交互流程。

图解:订单支付的业务流程和交互流程

结合下图来看看 订单支付的业务流程和交互流程。

请添加图片描述

订单支付流程, 分为 大致 的 6个步骤 :

1.下单/结算:

下单作为支付的入口,但并非起点,

支付相关的金额等信息全部来至结算,此时订单处于 未支付 状态。

2.申请支付:

用户开始申请支付,客户端调用支付服务,

此时在支付系统内产生一笔订单支付流水,这笔支付流水处于 未支付 状态。

3.发起支付:

支付服务调用 第三方支付平台,

通常, 第三方支付平台 是 钱包类的支付方式,

在发起支付这一步骤,支付平台会响应一些支付的链接,客户端会对链接进行相应的处理。

4.钱包支付:

用户进行支付,

用户 APP端直接拉去钱包进行支付。

5.支付回调:

用户完成支付之后,三方支付平台会回调 商户的支付服务 接口,通知支付结果。

6.更新订单状态:

支付服务 确认订单支付完成后,会向 订单服务同步 支付的结果。

订单服务变更服务的状态:未支付变更为 待发货

请添加图片描述

客户端通过轮询、长轮询,或者服务端主动推送的方式,在界面上变更订单状态。

请添加图片描述

图解:支付状态的变化

如下图,从支付流水角度来分析一下支付状态的变化:

请添加图片描述

1.从未支付,到有支付结果的终态,中间还有一个中间状态:支付中

2.户通过打开钱包–》完成支付–》支付回调,这段时间的支付流水就处于:支付中

重复下单的定义、危害、应对策略

什么是重复下单

现在问题来了, 什么是重复下单?

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

请添加图片描述

重复下单带来的危害

重复下单场景,第N次的下单会对数据进行打乱,导致系统整体数据异常

  • 库存数据异常
  • 金额数据异常
  • 优惠券数据异常
  • 等等

请添加图片描述

重复下单场景,第N次的下单需要等第一次下单操作完成

请添加图片描述

重复下单带来的危害, 总结起来,有以下几点:

1.系统资源占用与性能下降
  • 重复下单会占用系统资源,包括服务器、数据库等,特别是在下单高峰期,可能导致系统性能下降,响应速度变慢。

  • 重复请求可能引发系统拥堵,影响其他正常用户的购物体验。

2.订单处理复杂性增加
  • 商家在处理订单时,需要花费额外的时间和精力去识别、合并或取消重复订单,增加了订单处理的复杂性。
  • 重复订单可能导致库存数量出现错误,进而影响后续订单的履行。
3.财务结算与对账难度增大
  • 重复下单可能导致财务结算时出现混乱,需要花费更多时间和精力去核对和调整账目。
  • 对账过程中需要区分哪些是重复订单,哪些是有效订单,增加了对账的难度。
4.用户体验受损
  • 消费者在遇到重复下单时,可能会感到困惑和不满,影响对电商平台的信任度和忠诚度。
  • 重复下单可能导致消费者错过优惠活动或促销时机,影响其购物体验。
5.数据异常与决策误导
  • 重复下单的数据会干扰销售数据的准确性,可能导致商家在决策时受到误导。
  • 错误的销售数据可能影响商家的库存规划、生产计划等关键决策。
6.售后服务与退换货问题
  • 如果消费者对重复下单的商品申请了退换货,会增加售后服务的处理难度和成本。
  • 重复订单可能导致退换货政策执行混乱,影响消费者的售后体验。
7.安全风险与欺诈行为
  • 重复下单有时可能是恶意行为,如刷单、欺诈等,给电商平台带来安全风险。
  • 需要重点加强对重复下单的监控和识别,以防范潜在的安全风险。

重复下单问题,主要解决办法就是做好幂等,因为在分布式系统中,我们是没有办法保证用户一定不会快速点击两次下单。

Order 服务调用 Pay 服务,刚好网络超时,然后 Order 服务开始重试机制,于是 Pay 服务对同一支付请求,就接收到了两次,而且因为轮询负载均衡算法,请求落在了不同业务服务节点,所以一个分布式系统服务,须保证幂等性。

什么场景下回发生重复下单?

请添加图片描述

场景1:客户端bug

用户短时间内多次点击下单按钮,或浏览器刷新按钮导致。

比如下单的按键在点按之后,在没有收到服务器请求之前,按键的状态没有设为已禁用状态,还可以继续点击。又或者,在触摸屏下,用户手指的点按可能被手机操作系统识别为多次点击。

场景2:超时重试

Nginx或Spring Cloud Gateway 网关层、RPC通信重试或业务层重试,进行超时重试导致的。

用户的设备与服务器之间,可能是不稳定的网路。这样一个下单请求过去,服务器不一定及时返回结果。

超时最大的问题:从用户的角度,他无法确定下单的请求是否达到服务器,还是已经到了服务器但是返回结果时数据丢失了。所以用户无法区分到底这个订单是否下单成功。

场景3:用户APP强退/闪退之后重新下单

心急的用户可能会重启流程/重启App/重启手机。在这种强制的手段下,任何技术手段都会失效。

场景4:黑客或恶意用户

黑客或恶意用户使用postman等网络工具,重复恶意提交订单。

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

重复下单问题,本质上,就是下单操作的幂等性问题

说到底,“下单防重”的问题是属于“接口幂等性”的问题范畴。

什么是幂等性问题?

所谓幂等性,就是一次操作和多次操作同一个资源,所产生的影响均与一次操作的影响相同。

"幂等(idempotent、idempotence)是一个数学与计算机学概念,常见于抽象代数中。

幂等函数,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数。

幂等性,用数学语言表达就是:

f(x)=f(f(x))

维基百科的幂等性定义如下:

幂等(idempotent、idempotence)是一个数学与计算机学概念,常见于抽象代数中。

幂等函数,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数。

这些函数不会影响系统状态,也不用担心重复执行会对系统造成改变。

例如,“setTrue()”函数就是一个幂等函数,无论多次执行,其结果都是一样的,更复杂的操作幂等保证是利用唯一交易号(流水号)实现.

通俗点说:

一个接口如果幂等,不管被调多少次,只要参数不变,结果也不变。

幂等性是对于写操作来说的,一个写操作,一般都需要保证:

  • 幂等性

  • 可用性

  • ACID事务属性。

上述内容选自尼恩这篇硬核文章:

最系统的幂等性方案:一锁二判三更新

如何解决接口幂等问题

接口接口幂等问题,只需记住一句口令:一锁、二判、三更新。只需严格按照这个过程,那么就可以解决接口幂等问题,总结如下:

1.一锁:先加锁,可以加分布式锁、悲观锁都可以,但是一定是一个互斥锁。

2.二判:进行幂等性判断,可以基于状态机、业务流水表、数据库唯一索引等,进行重复操作的判断。

3.三更新:对数据进行更新,将数据进行持久化。

关于幂等性方案,请参见尼恩这篇硬核文章:

最系统的幂等性方案:一锁二判三更新

如何解决重复下单问题?

方案一:提交订单按钮置灰

防止用户提交,最常规的做法,就是客户端点击下单之后,在收到服务端响应之前,按钮置灰。

前端页面直接防止用户重复提交表单,但网络错误会导致重传,很多RPC框架、网关都有自动重试机制,所以重复请求在前端侧无法完全避免。

当然,这种方案也不是真的没有价值。

这种方案可以在高并发场景下,从浏览器端去拦住一部分请求,减少后端服务器的处理压力,达到过滤流量的效果。

**方案一优点:**简单。基本可以防止重复点击提交按钮造成的重复提交问题。

**方案一缺点:**前进后退操作,或者F5刷新页面等问题并不能得到解决。

方案二:请求唯一ID+数据库唯一索引约束

首先来向大家介绍一种最简单的、成本最低的解决方案。

防重是第一步,需要识别是否重复请求,

所以,需要客户端在请求下单接口的时候,需要生成一个唯一的请求号:requestId,服务端拿这个请求号,判断是否重复请求。

核心流程图:

请添加图片描述

实现的逻辑,流程如下:

  1. 当用户进入订单提交界面的时候,调用后端获取请求唯一ID,并将唯一ID值埋点在页面里面。

  2. 当用户点击提交按钮时,后端检查这个唯一ID是否用过,如果没有用过,继续后续逻辑;如果用过,就提示重复提交。

  3. 最关键的一步操作,就是把这个唯一ID 存入业务表中,同时设置这个字段为唯一索引类型,从数据库层面做防止重复提交。

对于下单流量不算高的系统,可以采用这种 请求唯一ID + 数据表增加唯一索引约束`的方式,来防止接口重复提交

但是这个并发量太低,10wqps高并发, 这个根本没法满足。

方案三:reids分布式锁+请求唯一ID

在上一个方案中,我们详细的介绍了对于下单流量不算高的系统,可以通过 请求唯一ID+数据表增加唯一索引约束`这种方案来实现防止接口重复提交

随着业务的快速增长,每一秒的下单请求次数,可能从几十上升到几百甚至几万。

面对这种下单流量越来越高的场景,此时数据库的访问压力会急剧上升,数据库会成为整个下单流程的瓶颈。

对于这样的场景,我们可以选择引入缓存中间件来缓解数据库高并发场景下的压力,

下面,我们以引入redis缓存中间件,向大家介绍具体的解决方案。

请添加图片描述

流程如下:

  1. 当用户进入订单提交界面的时候,调用后端获取请求唯一 ID,同时后端将请求唯一ID存储到redis中再返回给前端,前端将唯一 ID 值埋点在页面里面。

  2. 当用户点击提交按钮时,后端检查这个请求唯一 ID 是否存在,如果不存在,提示错误信息;如果存在,继续后续检查流程。

  3. 使用redis的分布式锁服务,对请求 ID 在限定的时间内进行加锁,如果加锁成功,继续后续流程;如果加锁失败,提示说明:服务正在处理,请勿重复提交。

  4. 最后一步,如果加锁成功后,需要将锁手动释放掉,以免再次请求时,提示同样的信息;同时如果任务执行成功,需要将redis中的请求唯一 ID 清理掉。

至于数据库是否需要增加字段唯一索引,理论上可以不用加,如果加了更保险。

这个通过扩展,可以满足 10wqps高并发要求。

具体的扩展方案, 即将在 《尼恩Java面试宝典》 配套视频 发布。

方案四:reids分布式锁+token

在上一个方案中,每次提交订单的时候,都需要调用服务端获取请求唯一ID:requestId,然后才能提交,这里面存在以下问题:

下单链路中,多了的一次请求, 这一次请求专门用于请求 request id。这次请求是否可以减少呢?

当然是可以的,比如, 可以用户的请求的特征数据,根据特定规则生成token,来替代 那个专用的 request id。

而不用专门去来减少一次客户端与服务端之间的交互次数,提高下单流程效率。

特定规则生成token, 比如说,可以组合一些核心参数,去生成token, 核心参数包括:
应用名+接口名+方法名+请求参数签名(请求header、body参数,取SHA1值)

请添加图片描述

组合一些核心参数,去生成token ,大致 流程如下:

  1. 用户点击提交按钮,服务端接受到请求后,通过规则计算出本次请求唯一ID值

  2. 使用redis的分布式锁服务,对请求 ID 在限定的时间内尝试进行加锁,如果加锁成功,继续后续流程;如果加锁失败,说明服务正在处理,请勿重复提交。

  3. 最后一步,如果加锁成功后,需要将锁手动释放掉,以免再次请求时,提示同样的信息。

方案四和方式三的最大不同,在于 唯一请求 ID 的生成 环节,

方案四 放在服务端通过组合来实现 唯一请求 ID 的生成 ,在保证防止接口重复提交的效果同时,也可以显著的降低接口测试复杂度!

方案四的性能,比方案三更高。

方案五:技术+产品+运营支持

如果经过上述方案处理,还是会有用户误操作,直到收到两份商品才发现下重了。

在实际设计中,无论多么好的技术,也不可能100%的拦截所有的可能性,必须依靠**技术+产品设计+运营支持**的综合手段才能解决这类问题。

此时就得依靠运营/客服的支持了。

所以即便京东这一类电商等也是配合运营手段进行处理。

实操:reids分布式锁+token 解决重复下单的问题

只讲理论,是耍流氓

40岁老架构师一直强调, 实操,实操,实操才是王道

比如咱们社群的 k8s 实操:

请添加图片描述

比如咱们社群的 AT+TCC模式混合事务实操 ):

此实操即将配合 《尼恩Java面试宝典视频》发布

请添加图片描述

接下来,咱们开始 reids分布式锁+token 解决重复下单的问题的实操

此实操即将配合 《尼恩Java面试宝典视频》发布

实操step1:使用AOP进行 BizToken 的无入侵生成

定义一个注解 BizToken

请添加图片描述

在业务层或者 控制层,进行BizToken 的使用

请添加图片描述

实操step2:编写服务验证逻辑,通过 aop 代理方式实现

请添加图片描述

此 aop 切面的 具体的实操演示,请参见 《尼恩Java面试宝典》 视频

实操step3:使用redission分布式锁保证幂等

在BizToken校验逻辑用到了redis分布式锁保证幂等,

redission分布式锁 具体实现逻辑如下:

请添加图片描述

通过封装 redission的分布式锁来实现 锁的功能:

请添加图片描述

具体的实现,委托到 redission的分布式锁来实现

请添加图片描述

具体的实操演示,请参见 《尼恩Java面试宝典》 视频

10wqps高并发,防止重复下单总结

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

实现幂等性需要先理解自身业务需求,根据业务逻辑来实现这样才合理,处理好其中的每一个结点细节,完善整体的业务流程设计,才能更好的保证系统正常运行。

说在最后:有问题找老架构取经

10wqps高并发,如何防止重复下单?

如果大家能对答如流,如数家珍,基本上 面试官会被你 震惊到、吸引到。

最终,让面试官爱到 “不能自已、口水直流”。offer, 也就来了。

在面试之前,建议大家系统化的刷一波 5000页《尼恩Java面试宝典PDF》,里边有大量的大厂真题、面试难题、架构难题。很多小伙伴刷完后, 吊打面试官, 大厂横着走。

在刷题过程中,如果有啥问题,大家可以来 找 40岁老架构师尼恩交流。

另外,如果没有面试机会,可以找尼恩来改简历、做帮扶。

遇到职业难题,找老架构取经, 可以省去太多的折腾,省去太多的弯路。

尼恩指导了大量的小伙伴上岸,前段时间,尼恩指导一个40岁+被裁小伙伴,拿到了一个年薪100W的offer。

10wqps高并发,如何防止重复下单?

如果大家能对答如流,如数家珍,基本上 面试官会被你 震惊到、吸引到。

最终,让面试官爱到 “不能自已、口水直流”。offer, 也就来了。

在面试之前,建议大家系统化的刷一波 5000页《尼恩Java面试宝典PDF》,里边有大量的大厂真题、面试难题、架构难题。很多小伙伴刷完后, 吊打面试官, 大厂横着走。

在刷题过程中,如果有啥问题,大家可以来 找 40岁老架构师尼恩交流。

另外,如果没有面试机会,可以找尼恩来改简历、做帮扶。

遇到职业难题,找老架构取经, 可以省去太多的折腾,省去太多的弯路。

尼恩指导了大量的小伙伴上岸,前段时间,尼恩指导一个40岁+被裁小伙伴,拿到了一个年薪100W的offer。

狠狠卷,实现 “offer自由” 很容易的, 前段时间一个武汉的跟着尼恩卷了2年的小伙伴, 在极度严寒/痛苦被裁的环境下, offer拿到手软, 实现真正的 “offer自由” 。

尼恩技术圣经系列PDF

  • 《NIO圣经:一次穿透NIO、Selector、Epoll底层原理》
  • 《Docker圣经:大白话说Docker底层原理,6W字实现Docker自由》
  • 《K8S学习圣经:大白话说K8S底层原理,14W字实现K8S自由》
  • 《SpringCloud Alibaba 学习圣经,10万字实现SpringCloud 自由》
  • 《大数据HBase学习圣经:一本书实现HBase学习自由》
  • 《大数据Flink学习圣经:一本书实现大数据Flink自由》
  • 《响应式圣经:10W字,实现Spring响应式编程自由》
  • 《Go学习圣经:Go语言实现高并发CRUD业务开发》

……完整版尼恩技术圣经PDF集群,请找尼恩领取

《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》PDF,请到下面公号【技术自由圈】取↓↓↓

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RA8889/RA8876显示自定义汉字字符方法

本文介绍用户自己生成的汉字字库如何通过RA8889/RA8876显示到液晶屏上。 实例效果图: 汉字字库通过第三方软件生成,点阵是从右到右排列,左高位排法,网上有许多软件可用,这边就不再列举。 汉字表如下,可根…

人工智能的发展史上,有哪些里程碑式的论文?

文章立意方向 在开始这篇文章之前,首先介绍下笔者的站位和看问题的角度:笔者是一个有过大厂从业经历的一线人工智能算法工程师,从2011年至今,亲身参与、亲眼看到人工智能的蓬勃发展的历程。手中的工具从基于概率论、导数的机器学…

面对汽车充电桩隐私泄露威胁,应该怎么做?

想必各位车主在第一次扫码或刷卡使用汽车充电桩时,都会出现类似于上图的请求,除了上述的定位权限外,运营商还会索要你的网络权限、相机权限、通知权限、设备信息权限、存储权限、电话权限等。 那么你知道这些权限充电桩获取后到底用于什么吗&…

知识融合:知识图谱构建的关键技术

目录 一、引言二、知识图谱基础2.1 知识表示三元组属性图 2.2 知识抽取实体抽取关系抽取属性抽取 三、知识融合的核心问题3.1 实体识别与链接实体识别实体链接 3.2 重复实体合并方法示例 3.3 关系融合挑战方法示例 四、知识融合技术深度解析4.1 基于规则的方法规则设计原则规则…

LeetCode-894. 所有可能的真二叉树【树 递归 记忆化搜索 动态规划 二叉树】

LeetCode-894. 所有可能的真二叉树【树 递归 记忆化搜索 动态规划 二叉树】 题目描述:解题思路一:分治,递归解题思路二:动态规划。关键思路是如果构造节点数目为 n 的真二叉树,此时可以从节点数目序列为 [(1,n−2),(3,…

来成都的国际数字影像产业园,开启文创产业园之旅

走进位于成都金牛区福堤路的国际数字影像产业园,仿佛置身于一个充满创意与活力的场域。这里是成都数字产业的聚集地,汇聚了上百家数字媒体相关企业,为成都文创产业注入了新的活力。在这里,你可以感受到浓厚的创新氛围,…

香港科技大学广州|智能制造学域博士招生宣讲会—东北大学专场

时间:2024年4月11日(星期四)14:00 地点:东北大学南湖校区逸夫楼101室 报名链接:https://www.wjx.top/vm/mmukLPC.aspx# 宣讲嘉宾:汤凯 教授/学域主任 跨学科重点研究领域 •工业4.0 •智能传感器、自动光…

数据安全之认识数据库防火墙

文章目录 一、什么是数据库防火墙二、数据库防火墙的主要功能三、数据库防火墙的工作原理四、数据库防火墙如何防护数据库免受SQL注入攻击五、数据库防火墙的部署方式六、数据库防火墙与网络防火墙的关系与区别七、数据库防火墙的应用场景 随着信息技术的快速发展,数…

蓝色wordpress外贸建站模板

蓝色wordpress外贸建站模板 https://www.mymoban.com/wordpress/7.html

如何利用Flutter将应用成功上架至iOS平台:详细指南

引言 🚀 Flutter作为一种跨平台的移动应用程序开发框架,为开发者提供了便利,使他们能够通过单一的代码库构建出高性能、高保真度的应用程序,同时支持Android和iOS两个平台。然而,完成Flutter应用程序的开发只是第一步…

深度解析C语言——预处理详解

对C语言有一定了解的同学&#xff0c;相信对预处理一定不会陌生。今天我们就来聊一聊一些预处理的相关知识。预处理是在编译之前对源文件进行简单加工的过程&#xff0c;主要是处理以#开头的命令&#xff0c;例如#include <stdio.h>、#define等。预处理是C语言的一个重要…

桥式起重机防摇输入整形

资料&#xff1a; 桥式起重机防摇定位控制系统开发&#xff0c;毕江涛 基于输入整形的桥式起重机货物摆动控制策略研究&#xff0c;王冰清 基于输入整形技术的门座起重机吊重摆动控制研究&#xff0c;王云飞 基于变增益 PID 控制的起重机防摇摆设计与仿真&#xff0c;郭瀛舟 ht…