分佈式系統接口冪等性

1.冪等性定義

1.1 數學定義

在數學裏,冪等有兩種主要的定義:- 在某二元運算下,冪等元素是指被本身重複運算(或對於函數是爲複合)的結果等於它本身的元素。例如,乘法下惟一兩個冪等實數爲0和1。即 s *s = s- 某一元運算爲冪等的時,其做用在任一元素兩次後會和其做用一次的結果相同。例如,高斯符號即是冪等的,即f(f(x)) = f(x)。express

1.2 HTTP規範的定義

在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

2. 何種接口提供冪等性

2.1 HTTP支持冪等性的接口

在HTTP規範中定義GET,PUT和DELETE方法應該具備冪等性。分佈式

  • GET方法

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方法是向服務器查詢,不會對系統產生反作用,具備冪等性(不表明每次請求都是相同的結果)函數

  • PUT方法

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

  • DELETE 方法

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方法是刪除服務器上的相關記錄。

2.2 實際業務

如今簡化爲這樣一個系統,用戶購買商品的訂單系統與支付系統;訂單系統負責記錄用戶的購買記錄已經訂單的流轉狀態(orderStatus),支付系統用於付款,提供

boolean pay(int accountid,BigDecimal amount) //用於付款,扣除用戶的

接口,訂單系統與支付系統經過分佈式網絡交互。

這種狀況下,支付系統已經扣款,可是訂單系統由於網絡緣由,沒有獲取到確切的結果,所以訂單系統須要重試。由上圖可見,支付系統並無作到接口的冪等性,訂單系統第一次調用和第二次調用,用戶分別被扣了兩次錢,不符合冪等性原則(同一個訂單,不管是調用了多少次,用戶都只會扣款一次)。若是須要支持冪等性,付款接口須要修改成如下接口:

boolean pay(int orderId,int accountId,BigDecimal amount)

經過orderId來標定訂單的惟一性,付款系統只要檢測到訂單已經支付過,則第二次調用不會扣款而會直接返回結果:

在不一樣的業務中不一樣接口須要有不一樣的冪等性,特別是在分佈式系統中,由於網絡緣由而未能獲得肯定的結果,每每須要支持接口冪等性。

3.分佈式系統接口冪等性

隨着分佈式系統及微服務的普及,由於網絡緣由而致使調用系統未能獲取到確切的結果從而致使重試,這就須要被調用系統具備冪等性。例如上文所闡述的支付系統,針對同一個訂單保證支付的冪等性,一旦訂單的支付狀態肯定以後,之後的操做都會返回相同的結果,對用戶的扣款也只會有一次。這種接口的冪等性,簡化到數據層面的操做:

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是相同的,對系統一樣沒有產生修改。

相關文章
相關標籤/搜索