一、什么是接口幂等性
所谓接口幂等性再就是客户端的一次请求或多次请求同一个资源产生相同的副作用。如当我们查询员工信息的时候,不论查多少次反会的结果相同,都是某个员工的信息。注意这里的相同并不是返回的信息是一样的,因为信息可能会被修改,所以说相同,都是这个员工的信息。
二、为什么需要接口幂等性
在高并发的场景中,可能由于网络延迟导致调用方没有及时的收到服务方的响应结果 。举个栗子,比如我们正在开发一个网上下单系统,当用户使用我们的系统下单时,我们就需要对该订单进行发货处理,我们的网上下单系统会调用发货系统进行发货,假如下单系统调用发货系统时网络延迟造成前端没响应,用户又点了几次,这样就会造成重复下单的问题。
在分布式场景中,假如你的某个服务部署了5台机器,前端请求调用,因为某些原因可能重复请求了两次,因为负载均衡算法落到了俩台机器上,可能会导致重复的业务处理逻辑;又比如说 在使用微服务组件,例如zuul,feign等 在超时的情况下会有重试机制,也可能会导致重试请求多次,如果业务方没有做好幂等性,就会导致业务处理出错,比如多次创建订单,多次扣款,这些坑都会导致很严重的问题
三、影响幂等性的操作
在增删改查四个操作中,尤其要注意增加和修改操作。
1、查询操作
查询对结果是不会有改变的,查询一次和查询多次没什么两样,因此查询操作具有天然的幂等性。
2、删除操作
删除一次和多次删除都是把数据删除。(注意可能返回结果不一样,删除的数据不存在,返回0,删除的数据多条,返回结果多个,在不考虑返回结果的情况下,删除操作也是具有幂等性的)。
3、更新操作
修改在大多场景下结果一样,但是如果是增量修改是需要保证幂等性的,如下例子:
把表中id为XXX的记录的A字段值设置为1,这种操作不管执行多少次都是幂等的
把表中id为XXX的记录的A字段值增加1,这种操作就不是幂等的
4、添加操作
增加在重复提交的场景下会出现幂等性问题,如以上的支付问题
四、保证幂等性
(1) 对于要操作的数据,在表中建立唯一索引字段。特别适用于进行一些新增数据,插入操作,比如创建订单,在MySQL业务表中建立唯一索引字段,当请求过来的时候,如果是多次重试,就违反了表中索引字段的唯一性,就会报错,业务自然会回滚。
(2) 还是基于MySQL数据库,在业务表中增加版本号字段,调用方每次请求数据的时候可以先获取version版本号,然后多传入一个version版本号字段,业务方在处理请求的时候,会去查新数据库中的version版本号,判断一下俩个version的值是否相同,如果version不相同,说明本次请求已经处理过了,直接返回。
(3) 基于业务状态进行判断,设计接口的时候,对于每一个业务操作能否操作,设置可以执行的状态,比如使用状态机模式,便于检查业务对象的状态,接受到请求要进行一些业务处理时,可以先行判断业务对象的状态,是否满足执行操作的条件,如果当前操作已经执行过了,那么状态就会发生变化,也就不能进行当前操作,直接返回。
(4) 可以在外部存储中设置一个单独的去重表,比如使用redis,每次请求过来,生成唯一的key。重复请求过来的时候判断一下这个key是否存在,如果存在,说明存在重复调用,直接返回。实现接口的幂等性 是业务接口方必须保证的基础功能,特别是服务与服务间的调用,可以使得服务接口在异常请求情况下,仍然保证接口的准确性,数据的准确性。