接口设计之幂等性
Posted 风暴之林
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了接口设计之幂等性相关的知识,希望对你有一定的参考价值。
接口幂等性的重要性
最近看到一个线上问题,意识到API设计要考虑很多,其中包括接口幂等性。
列举几个场景,突出本文核心思想。
场景1:请求正确执行了支付操作,但因为网络的原因,没有拿到支付结果,于是再去请求支付,造成重复支付。 场景2:恶意请求退款等操作,重复退款等。 场景3:对于一些异步回调的系统服务,重复处理回调结果。
分布式系统及微服务下,因为网络原因而导致调用系统未能获取到确切的结果从而导致重试,这就需要被调用系统接口具有幂等性。
何为接口幂等性
简单的说接口幂等性,就是执行一次请求,和执行多次请求所产生的结果是一致的。
哪些操作需要保证接口幂等性
查询,查询一次和查询多次,在数据不变的情况下,查询结果是一样的。select是天然的幂等操作。
删除,一般的删除操作后,对应数据就不在了,多次删除也不会有其他影响。
新增/更新,如表单重复提交,重复支付,需要幂等操作,否则会带来严重后果。
如何设计幂等性接口
后端接口
自己总体思路是依靠全局唯一性ID和mysql的排他锁,自定义乐观锁,主键唯一性等等。
1.依靠业务逻辑的判断
依靠业务逻辑的判断,如支付场景下,支付前取订单号判断是否已经支付,未支付则进行后续支付操作。当A,B两个请求达到系统请求支付接口,若A请求获取到状态已经支付,则成。 若获取到的状态都是未支付,此时一个线程,执行update操作(排它锁):
update t_order set status = 1 where order_id = 123 and status = 0
支付操作是事物的,当B去执行update失败后,我们进行回滚。
2.分布式锁
在分布式场景下,我们可以使用分布式锁(由redis或zookeeper实现)来实现幂等。 比如使用redis,依靠KEY+订单号的唯一性,请求接口时get(KEY+订单号),进行支付状态判断。但此方法对于高并发下,仍有可能会存在请求AB同时拿到可支付状态的情况,此时还需要依赖数据层面,mysql的悲观锁,或者自定义版本号version字段实现乐观锁。
3.排重表
大体思路:依赖Mysql主键唯一性,将唯一业务单号作为主键插入,实现互斥。
前端方面
对于普通用户的操作的一些高危的操作,前端页面上,做表单重复提交,N秒内限制重复提交,做友好提示,使穿过到后端的请求尽量有效。
开放平台API设计思考
自己工作涉及开放平台API,所以多多少少会去关注API的设计。
API设计时的思考方向
接口的命名、请求参数命名、出入参格式等
是否需要依赖于第三方和外系统,对外系统可能的影响
接口是否拆分、接口的扩展性
接口是否需要幂等
防刷、接口限流、降级
是否需要缓存、缓存穿透怎么办
白名单
TPS、并发数、响应时长。
---end---
以上是关于接口设计之幂等性的主要内容,如果未能解决你的问题,请参考以下文章