什么是接口的冪等性?
冪等作為一個數學概念,是指在某個一元運算過程中,任意次數的運算結果會與一次運算結束后的結果是相同的。在計算機操作中,一個冪等操作的特點是任意執行一次或者多次其操作所產生的影響與執行一次操作產生的影響結果是一樣的。
而所謂的冪等函數或者是冪等方法,則是指如果使用相同的參數進行重復執行,執行一次與執行多次所產生的結果是一樣的。也就是說函數或者是方法的不會對整個系統的狀態產生影響,也不用擔心多次執行函數會對系統產生改變。
接口冪等性則是指對于某個接口來講,請求一次的效果與請求多次對系統本身的影響是一樣的,也就是說第一次請求對系統產生了一定的影響,但是在后續請求過程中對系統產生的影響與第一次請求所產生的影響是一樣的,不會對系統帶來副作用。
為什么需要冪等性操作?
一般我們向外提供的接口都是可以正常返回信息的,也就不會出現重復調用接口的情況,但是如果遇到了網絡卡頓、頁面卡頓等情況有可能會出現頁面表單重復提交,網絡卡頓有可能會出現接口超時,造成的接口重復調用,或者是會出現惡意攻擊接口等情況。
而如何接口采用了冪等性操作其最大的優勢就是可以保證接口調用一次的效果與多次調用的效果是樣的,可以有效的避免因為重復調用而帶來的諸多系統未知錯誤。
引入冪等性之后可以簡化客戶端的處理邏輯,也能有效的防止表單的重復提交。但是引入冪等性所付出的代價就是后端處理邏輯會相對較復雜。所以,在引入冪等性操作的時候首先需要考慮的就是是否有必要引入,要根據實際的情況,結合具體的業務來完成對冪等性的引入。
如何所實現冪等性操作?
第一種、數據庫唯一鍵約束
數據庫的主鍵唯一性約束,一般比較適合對于插入操作的冪等性約束,因為我們知道,一張數據庫表中的一條記錄只能有一個唯一的主鍵來進行標識記錄。
使用數據庫主鍵唯一性約束作為冪等條件的時候需要注意的是,在實際開發中我們所使用的主鍵并不是數據庫中自增的主鍵,而是采用一些分布式的ID來充當組件,這樣才能有效的保證在分布式環境下的ID全局唯一性。這樣就可以保證冪等性的操作了。如下圖所示。
主要流程包括
- 客戶端執行創建請求,調用服務端接口
- 服務端執行業務邏輯采用分布式ID生成算法生成一個ID,將對應的ID插入對應記錄的主鍵,然后執行數據插入操作。
- 服務端將對應的數據插入到數據庫中,如果這個時候繼續有同樣的請求進入,則數據庫就會報出主鍵沖突的異常,這個時候就可以提示客戶度數據庫中已存在該條信息。請勿重復提交。
第二種、數據樂觀鎖操作
數據庫樂觀鎖操作是一種適用于更新操作的的冪等性解決方案。其實現需要我們在數據庫表中多加入一個字段來充當當前數據版本號的標識。這樣如果對這個數據進行更新的時候,就可以將該版本號作為標識來判斷數據是否被更新了。
update table set number1 = 123 where id= 1 and version = 5;
例如如果執行了上面這個操作之后,我們可以將id = 1 并且 version=5 的數據進行了更新,在更新成功之后,version就會變成 6,那么如果這個時候還有請求進入其帶入到更新操作依然會是version為5的操作,實際上,這個時候version已經變成了6,那么顯然version為5的操作就是找不到的,就可以保證了更新操作的冪等性。并且多次執行也不會對數據產生多余的影響。
第三種、利用Token防止重復提交
針對前后端分離項目,在客戶端連續進行點擊按鈕或者是調用超時的時候,利用Token就可以有效的防止重復提交。
簡單的說就是在調用方調用接口的時候先向后端請求了一個全局的TokenID,在請求的時候攜帶這個Token進行調用。后端需要根據這個Token作為key,用戶信息作為value到緩存中去驗證,如果存在對應的數據則執行刪除操作,然后后續的邏輯正常執行,如果沒有找到或者是找到的數據不匹配那么就無法執行后續的操作。有點像是令牌,這個令牌的獲取也可以進行流控操作。通過令牌的多少來控制發到后端請求的數量,這樣也可以有效的減輕后端系統的壓力。如下圖所示
- 服務端提供獲取Token的接口,這個Token可以是一個序列號也可以是一個分布式ID也可以其他唯一標識的字符串
- 客戶端調用獲取Token接口,這個時候服務端會生成一個Token串。
- 然后將該字符串存儲到redis緩存中,并且對這個Token串設置一個過期時間
- 將Token返回到客戶端,客戶端將Token攜帶到請求頭部
- 客戶端執行表單提交操作,并且將頭部的Token一起發到服務端
- 服務端獲取到頭部的Token之后,根據Token從Redis緩存中查找對應的信息。判斷是否存在。
- 如果服務端判斷到對應Key存在并且信息匹配,那么就刪除對應的key之后執行后續的業務,如果不存在則拋出異常提示重復提交異常。
注意,在并發場景中,執行Redis操作需要保證操作的原子性,這個時候有可能因為多個線程的進入而無法保證冪等性操作,這個是時候就需要采用分布式鎖機制來保證原子性操作。
第四種、唯一標識匹配
通過上面的分析,要想保證冪等性操作,其實主要就是要讓后續的操作邏輯能夠正常執行,那么這個時候,我們只需要保證每次請求都可以被唯一標識就可以保證是否重復提交。這個時候我們可以為每一個請求分配一個唯一的標識,這個標識是一個短期標識。并且一般由下游的服務來生成,這個時候就保證了當上游服務請求發到下游服務的時候兩者都知道對應的請求是否發生了變化。如下圖所示。
上面這個操作有點類似于Token獲取操作的思路。可以參照Token方式來對其進行理解。
總結
上面我們介紹了接口冪等性操作,并且介紹了保證冪等性的幾種方式。當然上述的這些內容在單體應用的情況下基本上不會出現問題,但是如果在并發場景下一定要結合鎖機制來使用才能有效的保證數據的安全性。