支付接口的冪等性設計


1. 什么是冪等性?

在數學中的冪等性定義:

在某二元運算下,冪等元素是指被自己重復運算(或對於函數是為復合)的結果等於它自己的元素。例如,乘法下唯一兩個冪等實數為0和1。 即 s * s = s

某一元運算為冪等時,其作用在任一元素兩次后會和其作用一次的結果相同。例如,高斯符號便是冪等的,即f(f(x)) = f(x)。

 

在HTTP/1.1規范中的冪等性定義:

如果一個請求方法在服務器上多次執行的預期影響與它只執行一次相同,那么這個請求方法就被認為具有冪等性。

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

 

2. 何種接口提供冪等性

2.1 HTTP支持冪等性的接口

在HTTP規范中定義GET,PUT和DELETE方法應該具有冪等性。

GET方法

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

PUT方法

也就是說PUT方法首先判斷系統中是否有相關的記錄,如果有記錄則更新該記錄,如果沒有則新增記錄。

DELETE 方法

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

聲明:本文轉載自蛙課網官方網站

更多好看、好用的資源盡在“蛙課網校”公眾號!小蛙等你哦~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM