幂等操作是指针对相同输入执行多次所产生的结果和执行一次所产生的结果相同,即重复执行不会带来副作用。
幂等和防重:幂等和防重有相似的地方,都是防止多次执行导致状态的改变,但是两者侧重点并不相同:⑴ 防重偏向于防止人为的重复提交,通常会对此类请求进行拦截并配合一些置灰操作防止重复动作触发。如针对表单提交,可以生成表单时携带token,表单提交时验证token,token验证后作废,重复提交时直接拦截,并将相关操作按钮置灰。
⑵ 幂等偏向于由于服务之间的调用超时导致的请求重试,因为我们只能明确知道成功或失败的含义,超时(或异常)有很多不确定性,可能请求就超时了,或者已经请求到了但响应超时了,无法确定最终的状态。于是系统为了确认第一次发起请求的最终结果发起重试,服务端针对多次重试不会产生副作用。
常见示例:订单创建接口超时导致重试,相同的输入重复调用订单创建接口是否会产生多个订单?
库存扣减接口超时导致重试,相同的输入重复调用库存扣减接口是否会导致库存多次扣减?
幂等解决方案:
基本思路就是保证交易信息的唯一性,使用唯一性来确认同一个请求,这个唯一凭证最好是全局唯一的数字,可参考Twitter的Snowflake(uuid也可以但并不具有任何肉眼可识别的意义,且字符串占用空间大于数字,索引效率差,不建议使用)。⑴ 由服务提供方进行幂等性保证,服务调用方超时即重试,服务提供方在业务处理前进行重复交易检查,如hash操作,查库,数据库表创建唯一性索引等保证多次请求只成功执行一次。
⑵由服务端提供结果查询,服务调用方超时重试时先去查询请求结果,如果查询结果已经处理成功就停止,否则再重新发起请求。
Http的幂等性:
Http Get方法通常用于获取资源,多次请求获取的资源应该是一致的,所以Get方式是幂等的。⑴ 注意Get请求也是可以携带报文体数据的,如果针对报文体数据进行处理则不一定是幂等的。⑵ 注意这里幂等是指多次请求并不会给获取资源带来副作用,即使返回的内容发生变化也不影响幂等性,也可以认为是幂等的。
Http Post方法显然不具备幂等性,多次提交会导致重复提交问题,所以需要我们防止重复提交。
小结:
幂等性是一个接口应该有的品格,但保证幂等性无疑会带来额外的开销,是否保证幂等性还是应该结合业务需求,涉及到金额,订单等关键业务时需要保证幂等,如果业务无特殊要求,则无需提供幂等性保证。