聊聊接口冪等性設(shè)計(jì)
300本計(jì)算機(jī)編程的經(jīng)典書籍下載
AI全套:Python3+TensorFlow打造人臉識(shí)別智能小程序
最新人工智能資料-Google工程師親授 Tensorflow-入門到進(jìn)階
黑馬頭條項(xiàng)目 - Java Springboot2.0(視頻、資料、代碼和講義)14天完整版
作者:pikaxiao
來源:blog.csdn.net/qq_36011946/article/details/104200262
冪等性設(shè)計(jì)
今天我們來聊聊接口的冪等性設(shè)計(jì),所謂冪等,就是任意多次執(zhí)行所產(chǎn)生的影響均與一次執(zhí)行的影響相同。 冪等性接口是指可以使用相同參數(shù)重復(fù)執(zhí)行,并能獲得相同結(jié)果的接口。這里就不展開數(shù)學(xué)中的定義了,有興趣的可以自行g(shù)oogle。
為什么接口需要冪等呢?
我們都知道,作為接口的調(diào)用方,對(duì)于接口調(diào)用的結(jié)果,一般會(huì)返回成功、失敗和超時(shí)。對(duì)于成功和失敗,都是明確的狀態(tài),調(diào)用放可以根據(jù)結(jié)果做相應(yīng)的處理,但是對(duì)于超時(shí),由于不確定是否成功請(qǐng)求了,作為調(diào)用方來說,所以一般都會(huì)選擇重試。而重試就會(huì)出現(xiàn)定義中描述的多次執(zhí)行。
可以從下面這個(gè)例子中加深一下理解:
創(chuàng)建訂單時(shí),需要減庫(kù)存,如果減庫(kù)存接口超時(shí)了,調(diào)用方重新調(diào)用一次(無論是否成功的執(zhí)行了減庫(kù)存代碼),應(yīng)該要保證不會(huì)多減一次庫(kù)存。
要保證不會(huì)多件一次庫(kù)存,一般有兩種做法:
接口提供方需要提供相應(yīng)的查詢接口。調(diào)用方在超時(shí)后去查詢一下是否成功。是否多扣一次庫(kù)存掌握在調(diào)用方手里。如果接口是提供給第三方使用的,就會(huì)存在一定的風(fēng)險(xiǎn)。 接口支持冪等。這樣冪等的保證完全掌握在提供方自己手里,完全不用擔(dān)心。
全局ID
要讓接口支持冪等,要怎么做呢,你可能會(huì)想到在減庫(kù)存之前增加一次查詢,已經(jīng)減過的直接返回不就完事了么?這樣確實(shí)能達(dá)到目的,可是會(huì)額外多了一次查詢,有沒有什么更優(yōu)的方法呢?
要保證減庫(kù)存操作的唯一性,可以在接口上多加一個(gè)參數(shù),這個(gè)參數(shù)必須全局唯一,數(shù)據(jù)庫(kù)設(shè)計(jì)表的時(shí)候這個(gè)字段要加上唯一索引,當(dāng)多次保存相同數(shù)據(jù)的時(shí)候,數(shù)據(jù)庫(kù)就會(huì)報(bào)錯(cuò),這就證明了接口已經(jīng)成功調(diào)用過,可以直接返回。
那這個(gè)全局ID由誰來分配呢?
1.可以創(chuàng)建一個(gè)分配中心,由中心統(tǒng)一分配。
優(yōu)點(diǎn):分配ID與業(yè)務(wù)集群解耦。
缺點(diǎn):需要單獨(dú)維護(hù)分配中心,這個(gè)分配中心也必須做成高可用集群,增加維護(hù)成本。
2.集成在業(yè)務(wù)服務(wù)集群。
優(yōu)點(diǎn):業(yè)務(wù)服務(wù)集群本來就是高可用的,無需提供額外保證。
缺點(diǎn):分配ID與業(yè)務(wù)耦合(這其實(shí)沒什么影響),需要保證業(yè)務(wù)服務(wù)集群生成ID的唯一性。
一般來說,后者是比較好的方案,我們只要提供一個(gè)能在集群上生成全局唯一ID的算法即可。
除了保證全局唯一,最好具備以下特點(diǎn)(非必須):
遞增,起碼保證每臺(tái)機(jī)器上的ID遞增。(保證數(shù)據(jù)庫(kù)性能) 明確的規(guī)則,ID的各個(gè)位都有具體的定義。(方便追溯)
接下來就來說說現(xiàn)階段常用的全局ID算法。
UUID
UUID設(shè)計(jì)的目的就是讓分布式系統(tǒng)中的所有元素,都能有唯一的辨識(shí)信息,而不需要通過中央控制端來做辨識(shí)信息的指定。關(guān)于UUID的設(shè)計(jì)原理可自行Google。
優(yōu)點(diǎn):實(shí)現(xiàn)簡(jiǎn)單(大多數(shù)編程語言都集成到工具庫(kù)了),本地生成,性能好,擴(kuò)展性高,不需要協(xié)定。
缺點(diǎn):無法遞增(消耗數(shù)據(jù)庫(kù)性能)、UUID過長(zhǎng)(消耗存儲(chǔ)空間)。
在中小型項(xiàng)目中,UUID會(huì)是不錯(cuò)的選擇。為什么這么說呢?面對(duì)并發(fā)度不高的系統(tǒng),數(shù)據(jù)庫(kù)性能一般不會(huì)達(dá)到瓶頸,所以說UUID是犧牲數(shù)據(jù)庫(kù)性能換取其優(yōu)點(diǎn)的一種選擇。
Snowflake
Snowflake是Twitter 的開源項(xiàng)目,它生成的ID是64bit的正整數(shù),結(jié)構(gòu)如圖:

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

正如我們前面講過的,要依賴于數(shù)據(jù)庫(kù)唯一性約束,當(dāng)數(shù)據(jù)庫(kù)報(bào)唯一性沖突時(shí),就說明這個(gè)求情已經(jīng)成功過了,不用再執(zhí)行,直接返回即可。
HTTP的冪等性
這里給出http請(qǐng)求的冪等性要求:

對(duì)于POST方法,可能會(huì)出現(xiàn)多次提交的問題,比如由于網(wǎng)絡(luò)不好等原因,造成請(qǐng)求超時(shí),這是用戶再點(diǎn)一次提交按鈕。對(duì)此一般的冪等性解決方法如下:
在提交的表單隱藏一個(gè)全局ID,這個(gè)全局ID需要提前向后端獲取,提交的時(shí)候把這個(gè)ID一起提交過來,按照上圖所描述的業(yè)務(wù)邏輯,來支持冪等。后端成功以后前端跳轉(zhuǎn),跳轉(zhuǎn)到GET請(qǐng)求,把剛才提交的數(shù)據(jù)展示出來。
小結(jié)
這篇講了冪等性設(shè)計(jì)的要點(diǎn),并給出了設(shè)計(jì)方案,大家可根據(jù)具體情況選擇合適的方案。
看完本文有收獲?請(qǐng)轉(zhuǎn)發(fā)分享給更多人
往期資源:
2019最新Python視頻:從入門到Swiper項(xiàng)目實(shí)戰(zhàn)
2019重磅高級(jí)資源:Java并發(fā)編程原理和實(shí)戰(zhàn)
最新黑馬大數(shù)據(jù)資源:深入解析docker容器化技術(shù)
最新Java后端實(shí)戰(zhàn)視頻:SSM框架在線商城系統(tǒng)
2019最新黑客技術(shù)之Windows網(wǎng)絡(luò)安全精講
