在数学里,幂等有两种主要的定义:- 在某二元运算下,幂等元素是指被本身重复运算(或对于函数是为复合)的结果等于它本身的元素。例如,乘法下惟一两个幂等实数为0和1。即 s *s = s- 某一元运算为幂等的时,其做用在任一元素两次后会和其做用一次的结果相同。例如,高斯符号即是幂等的,即f(f(x)) = f(x)。express
在HTTP/1.1规范中幂等性的定义是:服务器
A request method is considered "idempotent" if the intended effect onthe server of multiple identical requests with that method is the same as the effect for a single such request. Of the request methods defined by this specification, PUT, DELETE, and safe request methods are idempotent.网络
HTTP的幂等性指的是一次和屡次请求某一个资源应该具备相同的反作用。如经过PUT接口将数据的Status置为1,不管是第一次执行仍是屡次执行,获取到的结果应该是相同的,即执行完成以后Status =1。app
在HTTP规范中定义GET,PUT和DELETE方法应该具备幂等性。分布式
The GET method requests transfer of a current selected representatiofor the target resourceGET is the primary mechanism of information retrieval and the focus of almost all performance optimizations. Hence, when people speak of retrieving some identifiable information via HTTP, they are generally referring to making a GET request.ide
GET方法是向服务器查询,不会对系统产生反作用,具备幂等性(不表明每次请求都是相同的结果)函数
T he PUT method requests that the state of the target resource be created or replaced with the state defined by the representation enclosed in the request message payload.微服务
也就是说PUT方法首先判断系统中是否有相关的记录,若是有记录则更新该记录,若是没有则新增记录。this
The DELETE method requests that the origin server remove the association between the target resource and its current functionality. In effect, this method is similar to the rm command in UNIX: it expresses a deletion operation on the URI mapping of the origin server rather than an expectation that the previously associated information be deleted.spa
DELETE方法是删除服务器上的相关记录。
如今简化为这样一个系统,用户购买商品的订单系统与支付系统;订单系统负责记录用户的购买记录已经订单的流转状态(orderStatus),支付系统用于付款,提供
boolean pay(int accountid,BigDecimal amount) //用于付款,扣除用户的
接口,订单系统与支付系统经过分布式网络交互。
这种状况下,支付系统已经扣款,可是订单系统由于网络缘由,没有获取到确切的结果,所以订单系统须要重试。由上图可见,支付系统并无作到接口的幂等性,订单系统第一次调用和第二次调用,用户分别被扣了两次钱,不符合幂等性原则(同一个订单,不管是调用了多少次,用户都只会扣款一次)。若是须要支持幂等性,付款接口须要修改成如下接口:
boolean pay(int orderId,int accountId,BigDecimal amount)
经过orderId来标定订单的惟一性,付款系统只要检测到订单已经支付过,则第二次调用不会扣款而会直接返回结果:
在不一样的业务中不一样接口须要有不一样的幂等性,特别是在分布式系统中,由于网络缘由而未能获得肯定的结果,每每须要支持接口幂等性。
随着分布式系统及微服务的普及,由于网络缘由而致使调用系统未能获取到确切的结果从而致使重试,这就须要被调用系统具备幂等性。例如上文所阐述的支付系统,针对同一个订单保证支付的幂等性,一旦订单的支付状态肯定以后,之后的操做都会返回相同的结果,对用户的扣款也只会有一次。这种接口的幂等性,简化到数据层面的操做:
update userAmount set amount = amount - 'value' ,paystatus = 'paid' where orderId= 'orderid' and paystatus = 'unpay'
其中value是用户要减小的订单,paystatus表明支付状态,paid表明已经支付,unpay表明未支付,orderid是订单号。在上文中提到的订单系统,订单具备本身的状态(orderStatus),订单状态存在必定的流转。订单首先有提交(0),付款中(1),付款成功(2),付款失败(3),简化以后其流转路径如图:当orderStatus = 1 时,其前置状态只能是0,也就是说将orderStatus由0->1 是须要幂等性的
update Order set orderStatus = 1 where OrderId = 'orderid' and orderStatus = 0
当orderStatus 处于0,1两种状态时,对订单执行0->1 的状态流转操做应该是具备幂等性的。这时候须要在执行update操做以前检测orderStatus是否已经=1,若是已经=1则直接返回true便可。
可是若是此时orderStatus = 2,再进行订单状态0->1 时操做就没法成功,可是幂等性是针对同一个请求的,也就是针对同一个requestid保持幂等。
这时候再执行
update Order set orderStatus = 1 where OrderId = 'orderid' and orderStatus = 0
接口会返回失败,系统没有产生修改,若是再发一次,requestid是相同的,对系统一样没有产生修改。