关于防重,我是这么设计的

几年前,设计了一套增值服务购买流程,当时设计一整套下单购买流程。当时看了我们项目中多个订单防重,发现都不一样。结合了一点自己的思考,设计了一整套流程。当时感觉没什么,面试一问全扒瞎,特此回顾一下。

重复提交是项目中最常遇到的一个问题。为啥?不好界定啊,比如

  • 用户就是要买两单,手速快了点,防重了就不合适。
  • 大商户就是要用工具刷,就突出一个合理。
  • 前端忘记防抖,没辙。
  • 接口失败重试,机制就是这个机制
  • 队列重复消费了,也算是一种吧

会造成哪些问题呢?

  • 比如重复扣减库存?
  • 比如多加积分?
  • 比如重复下单?

场景还有很多,一般核心的业务场景都是要做预防的,具体哪些就要根据业务场景来考虑了

至于怎么解决,首先有两个概念,防重和幂等

  • 防重:防止重复提交,对于结果没有严格要求
  • 幂等:通俗点来说是防重的子集,再防重的基础上要求返回的结果一致

实际场景分&析解决方案

一个精简版的下单流程就是下面这个样子,下面就根据这个场景来聊一下防重。不谈场景就谈方案都是***!!!!

就拿上面的场景来说,我标注的三个地方都有可能发生重复提交的场景

  • 场景1:客户端重复网络抖动,前端重复提交,页面重复进入。此处的重复提交基本上都和客户端和网络还有用户脱不了关系
  • 场景2:可能得点就是重复消费,失败重复调用的场景。此处防重一般是第三方来考虑,稍后我也会分析分析。
  • 场景3:这个场景多半就是失败重试了。跟第三方,最大努力通知相关。

场景1 的解决方案

  1. client处理

一般来说,前端要做到流程不回退,防抖等操作,这个很重要,可以解决很大一部分重复请求

  1. 服务端处理
  • 带上token

请求的时候,可以前端台上token,或者后台提供token服务来解决这个问题,此token要保证特定时间内唯一性

  • 活锁CAS

如果不使用token也不使用redis,可以通过cas改变修改其他表的状态或者库存的方式,如果成功,才进行后续的订单创建

场景2 的解决方案

这个场景一般是三方服务要考虑的场景了,根据我对接调试的经验,一般是一种。

每次请求都生成一个订单,保证订单id唯一。每次请求都是新的一单,不会乱,出现问题也都是调用方的问题。一般的支付渠道也都是一次请求一单。

但是不能防止恶意请求的方式,为了解决这个问题,三方都会带上非对称加解密的方式进行请求校验。

场景3 的解决方案

第三个场景呢,也是在支付的时候会遇到的情况。有的支付渠道防控做的不大好,就是会有重复调用的情况。关键通知的时间不可控,一般来说是10分钟,20分钟,xxxxx进行累加。时间跨度比较大,也比较容易。

  • 根据己方或者三方订单号进行查询,判断,这种可以防止时间跨度比较大的情况
  • 唯一索引进行兜底,避免并发情况。

总结

当时设计的时候,防重部分,参考了项目中的蛮多案例的。这里只把一个下单流程中防重的点拿出来分析,适用性比较广。方案算不上高大上,但是适用性还可以,我觉得可以cover大部分场景,。

  • 前端需要保证下单后流程不回退
  • 唯一token校验防止重复
  • 依赖于上游服务校验防止重复
  • 每次下单都生成一单
  • 唯一索引
相关推荐
行百里er3 小时前
Redis 完结篇——Redis 热点问题在 Spring Boot 项目中实战
redis·后端
高频因子挖掘机4 小时前
只取最近 60 个交易日,却每次拉全历史:量化脚本变慢的原因与改法
后端·github·api
孟健5 小时前
从5000亿Token到83%字节匹配:AI逆向工程与重构的工程闭环实践
后端·架构·ai编程
码事漫谈5 小时前
丢得静悄悄,谈一谈 Agent 的记忆是怎么没的
后端
迪飞特科技5 小时前
智慧物业平台实战:Spring Boot 整合小程序实现报修巡检费用全流程
spring boot·后端·小程序
考虑考虑5 小时前
@JsonInclude注解使用
spring boot·后端·spring
IT_陈寒6 小时前
Vite的这个问题坑了我三天,原来如此解决!
前端·人工智能·后端
网易云信6 小时前
大模型能上岗做销售吗?我们让 12 款国产模型交了 420 份作业
前端·后端
CCblandy6 小时前
HTTP 长连接 3 类故障实测:[WinError 10053]、99 个 TIME_WAIT、69 次多余握手,4 种对策怎么选
后端·python·网络协议·http·云原生·性能优化·架构
蜗牛互联网6 小时前
Python Agent工具调用的白名单、参数校验与审批门禁
java·服务器·前端·人工智能·后端·python