当前位置: 首页 > 后端技术 > Java

接口幂等性设计

时间:2023-04-01 16:54:20 Java

什么是幂等性?幂等性是数学和计算机科学中的一个概念,经常出现在抽象代数中。编程中幂等操作的特点是它执行任意次数与执行一次效果相同。以上内容摘自百度百科,翻墙找了一些从Restful的角度对幂等性的解释,如下:在产生相同结果的同时重复进行相同的调用。换句话说,发出多个相同的请求与发出单个请求具有相同的效果。请注意,虽然幂等操作在服务器上产生相同的结果(无副作用),但响应本身可能不同(例如,资源的状态可能会在请求之间发生变化)。[从RESTful服务的角度来看,对于幂等操作(或服务调用),客户端可以重复进行相同的调用,同时产生相同的结果。换句话说,发出多个相同的请求与发出单个请求具有相同的效果。请注意,虽然幂等操作在服务器上产生相同的结果(没有副作用),但响应本身可能不同(例如,资源的状态可能会在请求之间发生变化)。]可见,幂等接口的设计强调多个相同的请求对服务器上的资源有相同的作用,没有任何副作用,但响应本身可以不同。举个栗子:比如一个GET请求,你在两次不同的时间请求,两次请求之间获取资源的状态可能发生了变化,但是两次请求参数相同,那么你可能会得到不同的结果响应,但是对服务器上的资源没有任何副作用,所以我们可以认为GET请求是天然幂等的。同理,DELETE请求也是天然幂等的,因为每次DELETE请求调用后,服务器上的状态都是一样的,只是响应不同。非幂等场景业务发展会导致非幂等场景主要有:MQ消息的重复消费;创建业务订单时,用户多次点击提交按钮,生成多个业务订单;三方因各种原因未收到回复,导致多次回调;上述非幂等场景,个人理解也不同,比如用户多次点击提交按钮,产生多条业务订单,此类场景的解决方案多为防止重复提交,反重复的本质是为了防止同一个请求被当成多个不同的请求;而支付回调和重复消费MQ消息都是第一次请求不知道结果(比如超时)或者失败的异常情况。发起多次请求的目的是多次确认第一次请求成功,但不会因为多次请求导致多次状态变化。个人认为,从请求时间间隔来看,多次点击按钮导致的多个业务订单多为短时间内的并发请求;而重复消费MQ消息和支付回调大多是因为两次相同的请求之间有一定的间隔。下面是支付宝支付成功的回调通知示例:程序执行后,必须打印出“success”(不带引号)。如果商户反馈给支付宝的字符不是成功的7个字符,支付宝服务器会继续重发通知,直到超过24小时22分钟。一般情况下,25小时内完成8次通知(通知间隔频率一般为:4m、10m、10m、1h、2h、6h、15h);如何保证幂等性,首先应该从幂等性(idempotencecondition)来考虑如何保证幂等性,换句话说,你如何判断多个传入的请求是相同的。这种幂等性的基础可以是每次交互产生的token,客户端的序列号或者唯一的业务订单号等等。非幂等性的副作用是什么?这个是基于业务定义的,比如重复点击生成多个订单,业务状态错误更改等。关于非幂等性的副作用,可以参考分布式幂等问题解决三部曲的第二部分。基于以上两种存在一定差异的非幂等场景,我们可以分别讨论不同非幂等场景下的处理方式。并发请求导致的非幂等场景的解决方法如前所述,防止重复提交。网上关于如何防止重复提交的文章大体类似。有几种解决方案可供参考。如果唯一索引是新增加的接口,则使用某个字段作为唯一索引。并发添加时,只能添加一个成功。当报唯一索引错误时,捕获异常重新查询即可。但是在分库分表的场景下,路由规则必须保证同一个请求落在同一个数据库的同一个表上,否则会导致求解失败。尝试{dao.insert(entity);//做生意}catch(DuplicateKeyExceptione){dao.select(param);//idempotentreturn}如果乐观锁是一个更新接口,状态字段或者版本字段作为幂等基础,使用字段作为更新标准。//会引起ABA问题,但不影响余额计算,version=version+1whereversion=#old_version#注意:乐观锁更新操作,最好使用主键或者唯一索引来更新,这个是行锁,否则更新updatetable_xxxset的时候会锁表aomunt=#new_amount#,version=version+1whereid=#id#andversion=#old_version#token机制。获取代币token,然后进行真正的业务请求。(如果是单机环境,缓存可以作为jvm级别的缓存。)分布式锁distributedlock的解决方案如图:以上图中的序号为依据幂等性(可以根据不同的业务选择不同的标志作为幂等性的依据),程序在执行前必须获取相应的锁,否则不会被处理。也就是说,在同一单位时间内,只有一个进程能够执行成功。串行请求引起的非幂等状态机有限状态机(finite-statemachine),又称有限状态自动机(finite-stateautomation),简称状态机,是有限状态数的表示以及这些状态之间的转换以及动作和其他行为的数学计算模型。从业务的角度来看,在业务的生命周期中存在不同的业务状态。使用状态机来控制业务流程中的状态转换是一个不错的选择。以下列命令为例。订单状态包括未付款、已付款、待退款、已退款、待发货、已发货、已签收。(真实顺序可能还有更多的状态,这里只是举例说明)。从图中可以看出只有pendingpayment才能更新为paid,pendingdelivery只有pendingdelivery才能更新为pendingdelivery。整个支付状态的改变被设计成不可逆的。使用状态机进行验证的一般处理步骤是在处理前判断当前状态是否满足预期状态。执行业务逻辑后,还会使用乐观锁定检查更改的状态。总结一下,多个相同的请求对服务器上的资源有相同的影响,没有任何副作用,但响应本身可以不同。常见的非幂等场景:1)多次重复点击;2)重复回调;3)MQ重复消费;保证幂等性的条件:幂等性的基础,副作用两种非幂等性场景的常见解决方案参考链接WhatIsEmpotence?幂等问题与设计思路,你不得不知道的一些幂等解决方案分布式幂等问题解决三部曲