冪等性本來是數學中的含義,表達式的是N次變換與1次變換的結果相同。
而RESTFul API中的冪等性是指調用某個方法1次或N次對資源產生的影響結果都是相同的,須要特別注意的是:這裏冪等性指的是對資源產生的影響結果,而不是調用HTTP方法的返回結果。
舉個例子,RESTFul API中的GET方法是查詢資源信息,不會對資源產生影響,因此它是符合冪等性的,可是每次調用GET方法返回的結果有可能不一樣(可能資源的某個屬性在調用GET方法以前已經被其餘方法修改了)。
實際上,在分佈式架構中的API冪等性不只僅針對RESTFul接口,而是對全部類型的接口適用,目的是爲了確保調用1次或N次接口時對資源的影響結果都是相同的。html
接口的冪等性確保了不管調用1次仍是N次對資源的影響都是相同的,這在某些場合下是很是有用的。
舉個例子,有這樣一個接口方法:pay(long account, int money),該方法用於銀行卡扣款支付,參數account爲帳戶ID,money爲須要扣除的錢數。當用戶從網頁上點擊支付按鈕時,在該方法的實現邏輯中須要從指定帳戶中扣除對應的商品價錢。若是支付操做已經成功執行,可是響應消息由於某種緣由未能及時返回給客戶端,這時候給用戶的體驗是多是未支付成功,若是此時再次點擊支付按鈕,那麼將再一次執行該方法,結果可能會致使用戶只買了一件商品卻花了雙份的錢,這固然是不合理的。整個流程以下圖所示:
git
固然,就上述例子的場景,爲了不用戶重複支付,是能夠經過別的方式解決的,好比:分佈式事務,或者根據支付狀態提示給予用戶進行提示等等。
可是,若是引入了分佈式事務,那麼將帶來實現上的複雜性,並且會影響到接口性能;而採起提示信息的方式並不能百分之百確保用戶不會重複支付,存在必定的風險。而若是接口符合冪等性,即:對同一個訂單不管是執行一次支付仍是屢次支付,在服務端都確保只會扣一次款,那麼既不須要引入分佈式事務的複雜性,也能從根本上解決重複支付的問題,這也就是接口符合冪等性的價值所在。github
總而言之,接口符合冪等性在能夠下降系統實現的複雜性,並能保證資源狀態的一致性。跨域
RESTFul風格的接口設計本質上使用的是HTTP協議方法,所以,RESTFul接口方法的冪等性指的就是HTTP方法的冪等性。
經常使用的HTTP方法有:OPTIONS(獲取服務器信息),HEAD(請求資源首部信息),GET(獲取資源),POST(建立資源),PUT(更新資源所有信息),PATCH(更新資源部分信息),DELETE(刪除資源)。那麼,這些HTTP方法的冪等性又是什麼樣的呢?
除了冪等性以外,HTTP方法的安全性是指不對資源產生修改。
以下是經常使用HTTP方法的冪等性和安全性總結:瀏覽器
HTTP方法名稱 | 是否冪等 | 是否安全 |
---|---|---|
OPTIONS | Y | Y |
HEAD | Y | Y |
GET | Y | Y |
PUT | Y | N |
DELETE | Y | N |
POST | N | N |
PATCH | N | N |
從上述表格中能夠看出,HTTP方法的冪等性和安全性並非同一個概念,以下是對個各個方法的冪等性和安全性解釋:安全
設計冪等性接口的關鍵在於保證接口不管是被調用1次仍是N次,它對資源所產生的影響都是相同的。
從上述HTTP方法的冪等性總結中能夠得知,HTTP協議的POST和PATCH方法都不是冪等性的(可是咱們卻常常會在RESTFul接口中使用到它們),那是否就意味中沒法將POST和PATCH方法設計爲冪等性接口了呢?答案顯然是否認的。在上述例子中,能夠將訂單ID也做爲方法參數之一,如:pay(long account, int money, long order),這樣在服務端確保一個訂單隻會被支付一次(訂單號是全局惟一的),那麼不管該方法被調用1次仍是N次結果都是同樣的,也就保證了接口的冪等性。固然,在哪些沒有訂單號的場景,能夠爲接口操做生成一個全局惟一的處理號ID,並把該處理號ID做爲方法參數之一,這樣在服務端確保一個處理號ID只會被執行一次就保證了接口的冪等性。
符合冪等性的接口調用流程描述以下圖所示:
服務器
雖說設計符合冪等性的接口在某些場合能夠下降系統的複雜性(如:能夠不用引入分佈式事務),可是並不是在全部場合的問題都能經過冪等性接口解決,在必要的時候依然須要引入分佈式事務處理這樣的框架。咱們不要也不能把接口冪等性做爲萬能的解決辦法,可是,咱們在設計接口時儘可能考慮符合冪等性處理是很是有價值的。restful
【參考】
http://blog.720ui.com/2016/restful_idempotent/ 如何理解RESTful的冪等性
https://www.cnblogs.com/weidagang2046/archive/2011/06/04/idempotence.html 理解HTTP冪等性
https://sofish.github.io/restcookbook/http%20methods/idempotency/ RESTful 手冊架構