分布式系統(tǒng)接口冪等性

1.冪等性定義


1.1 數(shù)學(xué)定義

在數(shù)學(xué)里,冪等有兩種主要的定義:

  • 在某二元運算下,冪等元素是指被自己重復(fù)運算(或?qū)τ诤瘮?shù)是為復(fù)合)的結(jié)果等于它自己的元素。例如,乘法下唯一兩個冪等實數(shù)為0和1。 即 s *s = s
  • 某一元運算為冪等的時,其作用在任一元素兩次后會和其作用一次的結(jié)果相同。例如,高斯符號便是冪等的,即f(f(x)) = f(x)。

1.2 HTTP規(guī)范的定義

在HTTP/1.1規(guī)范中冪等性的定義是:

A request method is considered "idempotent" if the intended effect on the 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.

如果一個請求方法在服務(wù)器上多次執(zhí)行的預(yù)期影響與它只執(zhí)行一次相同,那么這個請求方法就被認為具有冪等性。在此規(guī)范中,PUT、DELETE和安全method( GET, HEAD,OPTIONS, TRACE)都是冪等的。

HTTP的冪等性指的是一次和多次請求某一個資源應(yīng)該具有相同的副作用。如通過PUT接口將數(shù)據(jù)的Status置為1,無論是第一次執(zhí)行還是多次執(zhí)行,獲取到的結(jié)果應(yīng)該是相同的,即執(zhí)行完成之后Status =1。

2. 何種接口提供冪等性


2.1 HTTP支持冪等性的接口

在HTTP規(guī)范中定義GET,PUT和DELETE方法應(yīng)該具有冪等性。

  • 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.

GET方法是向服務(wù)器查詢,不會對系統(tǒng)產(chǎn)生副作用,具有冪等性(不代表每次請求都是相同的結(jié)果)

  • PUT方法

The 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方法首先判斷系統(tǒng)中是否有相關(guān)的記錄,如果有記錄則更新該記錄,如果沒有則新增記錄。

  • 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.

DELETE方法是刪除服務(wù)器上的相關(guān)記錄。

2.2 實際業(yè)務(wù)

現(xiàn)在簡化為這樣一個系統(tǒng),用戶購買商品的訂單系統(tǒng)與支付系統(tǒng);訂單系統(tǒng)負責(zé)記錄用戶的購買記錄已經(jīng)訂單的流轉(zhuǎn)狀態(tài)(orderStatus),支付系統(tǒng)用于付款,提供

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

接口,訂單系統(tǒng)與支付系統(tǒng)通過分布式網(wǎng)絡(luò)交互。


這種情況下,支付系統(tǒng)已經(jīng)扣款,但是訂單系統(tǒng)因為網(wǎng)絡(luò)原因,沒有獲取到確切的結(jié)果,因此訂單系統(tǒng)需要重試。 由上圖可見,支付系統(tǒng)并沒有做到接口的冪等性,訂單系統(tǒng)第一次調(diào)用和第二次調(diào)用,用戶分別被扣了兩次錢,不符合冪等性原則(同一個訂單,無論是調(diào)用了多少次,用戶都只會扣款一次)。 如果需要支持冪等性,付款接口需要修改為以下接口:

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

通過orderId來標(biāo)定訂單的唯一性,付款系統(tǒng)只要檢測到訂單已經(jīng)支付過,則第二次調(diào)用不會扣款而會直接返回結(jié)果:


在不同的業(yè)務(wù)中不同接口需要有不同的冪等性,特別是在分布式系統(tǒng)中,因為網(wǎng)絡(luò)原因而未能得到確定的結(jié)果,往往需要支持接口冪等性。

3.分布式系統(tǒng)接口冪等性


隨著分布式系統(tǒng)及微服務(wù)的普及,因為網(wǎng)絡(luò)原因而導(dǎo)致調(diào)用系統(tǒng)未能獲取到確切的結(jié)果從而導(dǎo)致重試,這就需要被調(diào)用系統(tǒng)具有冪等性。 例如上文所闡述的支付系統(tǒng),針對同一個訂單保證支付的冪等性,一旦訂單的支付狀態(tài)確定之后,以后的操作都會返回相同的結(jié)果,對用戶的扣款也只會有一次。這種接口的冪等性,簡化到數(shù)據(jù)層面的操作:

update userAmount set amount = amount - 'value' ,paystatus = 'paid' where orderId= 'orderid' and paystatus = 'unpay'

其中value是用戶要減少的訂單,paystatus代表支付狀態(tài),paid代表已經(jīng)支付,unpay代表未支付,orderid是訂單號。 在上文中提到的訂單系統(tǒng),訂單具有自己的狀態(tài)(orderStatus),訂單狀態(tài)存在一定的流轉(zhuǎn)。

訂單首先有提交(0),付款中(1),付款成功(2),付款失敗(3),簡化之后其流轉(zhuǎn)路徑如圖:


當(dāng)orderStatus = 1 時,其前置狀態(tài)只能是0,也就是說將orderStatus由0->1 是需要冪等性的

update Order set orderStatus = 1 where OrderId = 'orderid' and orderStatus = 0

當(dāng)orderStatus 處于0,1兩種狀態(tài)時,對訂單執(zhí)行0->1 的狀態(tài)流轉(zhuǎn)操作應(yīng)該是具有冪等性的。 這時候需要在執(zhí)行update操作之前檢測orderStatus是否已經(jīng)=1,如果已經(jīng)=1則直接返回true即可。

但是如果此時orderStatus = 2,再進行訂單狀態(tài)0->1 時操作就無法成功,但是冪等性是針對同一個請求的,也就是針對同一個requestid保持冪等。

這時候再執(zhí)行

update Order set orderStatus = 1 where OrderId = 'orderid' and orderStatus = 0

接口會返回失敗,系統(tǒng)沒有產(chǎn)生修改,如果再發(fā)一次,requestid是相同的,對系統(tǒng)同樣沒有產(chǎn)生修改。

References


冪等
HTTP冪等性概念和應(yīng)用
What Is Idempotent in REST?
REST之中的冪等指的是什么?
Hypertext Transfer Protocol (HTTP/1.1)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,981評論 19 139
  • 引言 互聯(lián)網(wǎng)時代以來,基于HTTP協(xié)議提供Web API的方式幾乎成了約定俗成的規(guī)范,再加上近年來分布式SOA、微...
    阿堃堃堃堃閱讀 8,744評論 1 10
  • 原文鏈接:https://https://howardwchen.com/2017/09/18/talk-abou...
    守望者Howard閱讀 6,422評論 1 6
  • salve 上, root@slave2:/opt/spark-2.1.0-bin-hadoop2.6/conf#...
    焉知非魚閱讀 228評論 0 1
  • 姓名:魏正君《六項精進》第270期感謝2組 公司:綿陽大北農(nóng)農(nóng)牧科技有限公司 【日精進打卡第44天】 【知~學(xué)習(xí)】...
    莫心莫肺閱讀 178評論 0 0