接口設計之冪等性設計

冪等性設計

今天我們來聊聊接口的冪等性設計,所謂冪等,就是任意多次執行所產生的影響均與一次執行的影響相同。 冪等性接口是指可以使用相同參數重複執行,並能獲得相同結果的接口。這裏就不展開數學中的定義了,有興趣的可以自行google。

爲什麼接口需要冪等呢?

我們都知道,作爲接口的調用方,對於接口調用的結果,一般會返回成功、失敗和超時。對於成功和失敗,都是明確的狀態,調用放可以根據結果做相應的處理,但是對於超時,由於不確定是否成功請求了,作爲調用方來說,所以一般都會選擇重試。而重試就會出現定義中描述的多次執行。

可以從下面這個例子中加深一下理解:

創建訂單時,需要減庫存,如果減庫存接口超時了,調用方重新調用一次(無論是否成功的執行了減庫存代碼),應該要保證不會多減一次庫存。

要保證不會多件一次庫存,一般有兩種做法:

  1. 接口提供方需要提供相應的查詢接口。調用方在超時後去查詢一下是否成功。是否多扣一次庫存掌握在調用方手裏。如果接口是提供給第三方使用的,就會存在一定的風險。
  2. 接口支持冪等。這樣冪等的保證完全掌握在提供方自己手裏,完全不用擔心。

全局ID

要讓接口支持冪等,要怎麼做呢,你可能會想到在減庫存之前增加一次查詢,已經減過的直接返回不就完事了麼?這樣確實能達到目的,可是會額外多了一次查詢,有沒有什麼更優的方法呢?

要保證減庫存操作的唯一性,可以在接口上多加一個參數,這個參數必須全局唯一,數據庫設計表的時候這個字段要加上唯一索引,當多次保存相同數據的時候,數據庫就會報錯,這就證明了接口已經成功調用過,可以直接返回。

那這個全局ID由誰來分配呢?

  1. 可以創建一個分配中心,由中心統一分配。

    優點:分配ID與業務集羣解耦。

    缺點:需要單獨維護分配中心,這個分配中心也必須做成高可用集羣,增加維護成本。

  2. 集成在業務服務集羣

    優點:業務服務集羣本來就是高可用的,無需提供額外保證。

    缺點:分配ID與業務耦合(這其實沒什麼影響),需要保證業務服務集羣生成ID的唯一性。

一般來說,後者是比較好的方案,我們只要提供一個能在集羣上生成全局唯一ID的算法即可。

除了保證全局唯一,最好具備以下特點(非必須):

  • 遞增,起碼保證每臺機器上的ID遞增。(保證數據庫性能)
  • 明確的規則,ID的各個位都有具體的定義。(方便追溯)

接下來就來說說現階段常用的全局ID算法。

UUID

UUID設計的目的就是讓分佈式系統中的所有元素,都能有唯一的辨識信息,而不需要通過中央控制端來做辨識信息的指定。關於UUID的設計原理可自行Google。

優點:實現簡單(大多數編程語言都集成到工具庫了),本地生成,性能好,擴展性高,不需要協定。

缺點:無法遞增(消耗數據庫性能)、UUID過長(消耗存儲空間)。

在中小型項目中,UUID會是不錯的選擇。 爲什麼這麼說呢?面對併發度不高的系統,數據庫性能一般不會達到瓶頸,所以說UUID是犧牲數據庫性能換取其優點的一種選擇。

Snowflake

Snowflake是Twitter 的開源項目,它生成的ID是64bit的正整數,結構如圖:

在這裏插入圖片描述

  • 1bit:固定爲0,二進制中最高位爲符號位,0爲整數,1位負數。所以固定爲0表示生成的ID都爲正數
  • 41bit:作爲毫秒數,大約能用69年。
  • 10bit:作爲機器編號(5bit是數據中心ID,5bit爲機器ID)。支持1204個實例。
  • 12bit:序列號,一毫秒最多生成2^12=4096個。

優點:遞增,且按時間有序。性能高,可根據情況分配bit。

缺點:依賴機器時鐘。在分佈式系統中,各個機器上的時間不可能完全一樣,在同步各機器的時間時,可能會造成重複ID。

在高併發的業務下,Snowflake生成的整數ID的存儲和讀取性能都要優於UUID。 現階段國內有很多基於Snowflake算法的特定實現,比如百度的UidGenerator。

關於Redis和MongoDB的設計這裏就不展開了。畢竟要強依賴於存儲系統,添加了維護成本和風險點。

業務邏輯

在這裏插入圖片描述

正如我們前面講過的,要依賴於數據庫唯一性約束,當數據庫報唯一性衝突時,就說明這個求情已經成功過了,不用再執行,直接返回即可。

HTTP的冪等性

這裏給出http請求的冪等性要求:

方法 冪等 描述
GET 天然冪等
HEAD 天然冪等
OPTIONS 天然冪等
DELETE 天然冪等
PUT 天然冪等
POST × 需要支持冪等

對於POST方法,可能會出現多次提交的問題,比如由於網絡不好等原因,造成請求超時,這是用戶再點一次提交按鈕。對此一般的冪等性解決方法如下:

  • 在提交的表單隱藏一個全局ID,這個全局ID需要提前向後端獲取,提交的時候把這個ID一起提交過來,按照上圖所描述的業務邏輯,來支持冪等。
  • 後端成功以後前端跳轉,跳轉到GET請求,把剛纔提交的數據展示出來。

小結

這篇講了冪等性設計的要點,並給出了設計方案,大家可根據具體情況選擇合適的方案。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章