點擊上方藍色字體,選擇“標星公眾號”
優(yōu)質(zhì)文章,第一時間送達
冪等性設計
今天我們來聊聊接口的冪等性設計,所謂冪等,就是任意多次執(zhí)行所產(chǎn)生的影響均與一次執(zhí)行的影響相同。 冪等性接口是指可以使用相同參數(shù)重復執(zhí)行,并能獲得相同結(jié)果的接口。這里就不展開數(shù)學中的定義了,有興趣的可以自行g(shù)oogle。
為什么接口需要冪等呢?
我們都知道,作為接口的調(diào)用方,對于接口調(diào)用的結(jié)果,一般會返回成功、失敗和超時。對于成功和失敗,都是明確的狀態(tài),調(diào)用放可以根據(jù)結(jié)果做相應的處理,但是對于超時,由于不確定是否成功請求了,作為調(diào)用方來說,所以一般都會選擇重試。而重試就會出現(xiàn)定義中描述的多次執(zhí)行。
可以從下面這個例子中加深一下理解:
創(chuàng)建訂單時,需要減庫存,如果減庫存接口超時了,調(diào)用方重新調(diào)用一次(無論是否成功的執(zhí)行了減庫存代碼),應該要保證不會多減一次庫存。
要保證不會多件一次庫存,一般有兩種做法:
接口提供方需要提供相應的查詢接口。調(diào)用方在超時后去查詢一下是否成功。是否多扣一次庫存掌握在調(diào)用方手里。如果接口是提供給第三方使用的,就會存在一定的風險。
接口支持冪等。這樣冪等的保證完全掌握在提供方自己手里,完全不用擔心。
全局ID
要讓接口支持冪等,要怎么做呢,你可能會想到在減庫存之前增加一次查詢,已經(jīng)減過的直接返回不就完事了么?這樣確實能達到目的,可是會額外多了一次查詢,有沒有什么更優(yōu)的方法呢?
要保證減庫存操作的唯一性,可以在接口上多加一個參數(shù),這個參數(shù)必須全局唯一,數(shù)據(jù)庫設計表的時候這個字段要加上唯一索引,當多次保存相同數(shù)據(jù)的時候,數(shù)據(jù)庫就會報錯,這就證明了接口已經(jīng)成功調(diào)用過,可以直接返回。
那這個全局ID由誰來分配呢?
可以創(chuàng)建一個分配中心,由中心統(tǒng)一分配。
優(yōu)點:分配ID與業(yè)務集群解耦。
缺點:需要單獨維護分配中心,這個分配中心也必須做成高可用集群,增加維護成本。
集成在業(yè)務服務集群。
優(yōu)點:業(yè)務服務集群本來就是高可用的,無需提供額外保證。
缺點:分配ID與業(yè)務耦合(這其實沒什么影響),需要保證業(yè)務服務集群生成ID的唯一性。
一般來說,后者是比較好的方案,我們只要提供一個能在集群上生成全局唯一ID的算法即可。
除了保證全局唯一,最好具備以下特點(非必須):
接下來就來說說現(xiàn)階段常用的全局ID算法。
UUID
UUID設計的目的就是讓分布式系統(tǒng)中的所有元素,都能有唯一的辨識信息,而不需要通過中央控制端來做辨識信息的指定。關(guān)于UUID的設計原理可自行Google。
優(yōu)點:實現(xiàn)簡單(大多數(shù)編程語言都集成到工具庫了),本地生成,性能好,擴展性高,不需要協(xié)定。
缺點:無法遞增(消耗數(shù)據(jù)庫性能)、UUID過長(消耗存儲空間)。
在中小型項目中,UUID會是不錯的選擇。 為什么這么說呢?面對并發(fā)度不高的系統(tǒng),數(shù)據(jù)庫性能一般不會達到瓶頸,所以說UUID是犧牲數(shù)據(jù)庫性能換取其優(yōu)點的一種選擇。
Snowflake
Snowflake是Twitter 的開源項目,它生成的ID是64bit的正整數(shù),結(jié)構(gòu)如圖:

1bit:固定為0,二進制中最高位為符號位,0為整數(shù),1位負數(shù)。所以固定為0表示生成的ID都為正數(shù)
41bit:作為毫秒數(shù),大約能用69年。
10bit:作為機器編號(5bit是數(shù)據(jù)中心ID,5bit為機器ID)。支持1204個實例。
12bit:序列號,一毫秒最多生成2^12=4096個。
優(yōu)點:遞增,且按時間有序。性能高,可根據(jù)情況分配bit。
缺點:依賴機器時鐘。在分布式系統(tǒng)中,各個機器上的時間不可能完全一樣,在同步各機器的時間時,可能會造成重復ID。
在高并發(fā)的業(yè)務下,Snowflake生成的整數(shù)ID的存儲和讀取性能都要優(yōu)于UUID。 現(xiàn)階段國內(nèi)有很多基于Snowflake算法的特定實現(xiàn),比如百度的UidGenerator。
關(guān)于Redis和MongoDB的設計這里就不展開了。畢竟要強依賴于存儲系統(tǒng),添加了維護成本和風險點。
業(yè)務邏輯

正如我們前面講過的,要依賴于數(shù)據(jù)庫唯一性約束,當數(shù)據(jù)庫報唯一性沖突時,就說明這個求情已經(jīng)成功過了,不用再執(zhí)行,直接返回即可。
HTTP的冪等性
這里給出http請求的冪等性要求:
| 方法 | 冪等 | 描述 |
|---|
| GET | √ | 天然冪等 |
| HEAD | √ | 天然冪等 |
| OPTIONS | √ | 天然冪等 |
| DELETE | √ | 天然冪等 |
| PUT | √ | 天然冪等 |
| POST | × | 需要支持冪等 |
對于POST方法,可能會出現(xiàn)多次提交的問題,比如由于網(wǎng)絡不好等原因,造成請求超時,這是用戶再點一次提交按鈕。對此一般的冪等性解決方法如下:
小結(jié)
這篇講了冪等性設計的要點,并給出了設計方案,大家可根據(jù)具體情況選擇合適的方案。
作者 | pikaxiao
來源 | csdn.net/qq_36011946/article/details/104200262