什么是接口幂等性?为什么会产生这个问题?如何保证接口幂等性?
时间:2021-08-13 17:13:07
[导读]博主负责的项目报了一个问题,用户操作回退失效。我们的设计里,操作回退是回到操作前的状态。经过查看日志发现,用户之前的操作做了两次,也就是说提交操作的接口被调用了两次,导致之用户上一次的状态和这一次的状态是一样的,所以操作回退是没有问题的,问题出在了操作的接口被调用了两次。对于防止...
博主负责的项目报了一个问题,用户操作回退失效。我们的设计里,操作回退是回到操作前的状态。经过查看日志发现,用户之前的操作做了两次,也就是说提交操作的接口被调用了两次,导致之用户上一次的状态和这一次的状态是一样的,所以操作回退是没有问题的,问题出在了操作的接口被调用了两次。
对于防止重复提交,是放在前端控制的,用户点击完按钮之后,后台返回成功的结果,按钮就不可见,实践证明,客户端的限制操作不是绝对可靠的。
针对上面的场景,就引入了今天的问题,什么是接口幂等性?如何保证接口幂等性?
什么是接口幂等性?
首先看看幂等性的概念:幂等性原本是数学上的概念,用在接口上就可以理解为:**同一个接口,多次发出同一个请求,必须保证操作只执行一次。**调用接口发生异常并且重复尝试时,总是会造成系统所无法承受的损失,所以必须阻止这种现象的发生。
比如下面这些情况,如果没有实现接口幂等性会有很严重的后果:支付接口,重复支付会导致多次扣钱 ;订单接口,同一个订单可能会多次创建。
为什么会产生接口幂等性问题?
那么,什么情况下,会产生接口幂等性的问题呢?-
网络波动, 可能会引起重复请求
-
用户重复操作,用户在操作时候可能会无意触发多次下单交易,甚至没有响应而有意触发多次交易应用
-
使用了失效或超时重试机制(Nginx重试、RPC重试或业务层重试等)
-
页面重复刷新
-
使用浏览器后退按钮重复之前的操作,导致重复提交表单
-
使用浏览器历史记录重复提交表单
-
浏览器重复的HTTP请求
-
定时任务重复执行
-
用户双击提交按钮
如何保证接口幂等性?
那么最关键的来了,如何保证接口幂等性?解决办法分为两个方向,一个方向是客户端防止重复调用,一个是服务端进行校验。当然,客户端防止重复提交并不是绝对可靠的,优点是实现起来比较简单。
-
按钮只可操作一次
-
token机制
-
使用Post/Redirect/Get模式
-
在session存放特殊标志
-
使用唯一索引防止新增脏数据
-
乐观锁
update table set version = version 1 where id = #{id} and version = #{version}
示例: 当有重复请求的时候,第一个请求会获取当前商品的version版本号,得到的version为1,紧接着由于第一个请求还没更新商品的version,第二个请求获取的version依然也是1, 这时候第一个请求操作更新的时候带上version并作为条件并且自增更新,这时候商品的version就会变成2,当第二个请求去操作更新的时候明显version不一致导致更新失败。
-
select insert or update or delete
-
分布式锁
-
状态机幂等
-
防重表
注: 最好结合状态机幂等先判断一下
-
缓冲队列
-
全局唯一号





