基於Redis&MySQL介面冪等性設計
欲把相思說似誰,淺情人不知。
1、冪等
冪等性即多次呼叫介面或方法不會改變業務狀態,可以保證重複呼叫的結果和單次呼叫的結果一致。
2、冪等使用場景
前端重複提交
使用者註冊、建立商品、提交訂單、轉賬、支付等操作,前端都會提交一些資料給後臺服務,後臺需要根據使用者提交的資料在資料庫中建立記錄。如果使用者不小心多點了幾次,後端收到了好幾次提交,這時就會在資料庫中重複建立了多條記錄。這就是介面沒有冪等性帶來的bug。
介面超時重試
對於給第三方呼叫的介面,有可能會因為網路原因而呼叫失敗,這種情況一般在設計的時候會對介面呼叫加上失敗重試的機制,如果第一次呼叫已經執行了一半時發生了網路異常,這時再次呼叫時就會因為髒資料的存在而出現呼叫異常。
訊息重複消費
在使用訊息中介軟體來處理訊息佇列,且手動 ack 確認訊息被正常消費時。如果消費者突然斷開連線,那麼已經執行了一半的訊息會重新放回佇列。
當訊息被其他消費者重新消費時,如果沒有冪等性,就會導致訊息重複消費引起結果異常如資料庫重複資料等。
3、解決方案
基於Token
通過token 機制實現介面的冪等性,是一種比較通用性的實現方法。
具體流程步驟:
-
客戶端會先傳送一個請求去獲取 token,服務端會生成一個全域性唯一的 ID 作為 token 儲存在 redis 中,同時把這個 ID 返回給客戶端;
-
客戶端第二次呼叫業務請求的時候必須攜帶這個 token;
-
服務端會校驗這個 token,如果校驗成功,則執行業務,並刪除 redis 中的 token;
-
如果校驗失敗,說明 redis 中已經沒有對應的 token,則表示重複操作,直接返回指定的結果給客戶端。
基於MySQL
基於MySQL實現方式是利用了 mysql 唯一索引的特性。
具體流程步驟:
-
建立一張去重表,其中某個欄位需要建立唯一索引,如訂單ID,使用者ID;
-
客戶端去請求服務端,服務端會將這次請求的一些資訊插入這張去重表中;
-
因為表中某個欄位帶有唯一索引,如果插入成功,證明表中沒有這次請求的資訊,則執行後續的業務邏輯;
-
如果插入失敗,則代表已經執行過當前請求,直接返回。
基於Redis
基於Redis是利用了 SETNX 命令實現的。
SETNX key value:將 key 的值設為 value ,當且僅當 key 不存在。若給定的 key 已經存在,則 SETNX 不做任何動作。
該命令在設定成功時返回 1,設定失敗時返回 0。
具體流程步驟:
-
客戶端先請求服務端,會拿到一個能代表這次請求業務的唯一欄位;
-
將該欄位以 SETNX 的方式存入 redis 中,並根據業務設定相應的超時時間;
-
如果設定成功,證明這是第一次請求,則執行後續的業務邏輯;
-
如果設定失敗,則代表已經執行過當前請求,直接返回。
欲把相思說似誰
淺情人不知