基於Redis&MySQL介面冪等性設計

濤姐濤哥發表於2022-01-26

基於Redis&MySQL介面冪等性設計

 

      欲把相思說似誰,淺情人不知。

 

1、冪等

冪等性即多次呼叫介面或方法不會改變業務狀態,可以保證重複呼叫的結果和單次呼叫的結果一致。

2、冪等使用場景

前端重複提交

使用者註冊、建立商品、提交訂單、轉賬、支付等操作,前端都會提交一些資料給後臺服務,後臺需要根據使用者提交的資料在資料庫中建立記錄。如果使用者不小心多點了幾次,後端收到了好幾次提交,這時就會在資料庫中重複建立了多條記錄。這就是介面沒有冪等性帶來的bug。

介面超時重試

對於給第三方呼叫的介面,有可能會因為網路原因而呼叫失敗,這種情況一般在設計的時候會對介面呼叫加上失敗重試的機制,如果第一次呼叫已經執行了一半時發生了網路異常,這時再次呼叫時就會因為髒資料的存在而出現呼叫異常。

訊息重複消費
在使用訊息中介軟體來處理訊息佇列,且手動 ack 確認訊息被正常消費時。如果消費者突然斷開連線,那麼已經執行了一半的訊息會重新放回佇列。
當訊息被其他消費者重新消費時,如果沒有冪等性,就會導致訊息重複消費引起結果異常如資料庫重複資料等。

3、解決方案

基於Token

通過token 機制實現介面的冪等性,是一種比較通用性的實現方法。

具體流程步驟:

  1. 客戶端會先傳送一個請求去獲取 token,服務端會生成一個全域性唯一的 ID 作為 token 儲存在 redis 中,同時把這個 ID 返回給客戶端;

  2. 客戶端第二次呼叫業務請求的時候必須攜帶這個 token;

  3. 服務端會校驗這個 token,如果校驗成功,則執行業務,並刪除 redis 中的 token;

  4. 如果校驗失敗,說明 redis 中已經沒有對應的 token,則表示重複操作,直接返回指定的結果給客戶端。

基於MySQL

基於MySQL實現方式是利用了 mysql 唯一索引的特性。

具體流程步驟:

  1. 建立一張去重表,其中某個欄位需要建立唯一索引,如訂單ID,使用者ID;

  2. 客戶端去請求服務端,服務端會將這次請求的一些資訊插入這張去重表中;

  3. 因為表中某個欄位帶有唯一索引,如果插入成功,證明表中沒有這次請求的資訊,則執行後續的業務邏輯;

  4. 如果插入失敗,則代表已經執行過當前請求,直接返回。

基於Redis

基於Redis是利用了 SETNX 命令實現的。

SETNX key value:將 key 的值設為 value ,當且僅當 key 不存在。若給定的 key 已經存在,則 SETNX 不做任何動作。

該命令在設定成功時返回 1,設定失敗時返回 0。

具體流程步驟:

  1. 客戶端先請求服務端,會拿到一個能代表這次請求業務的唯一欄位;

  2. 將該欄位以 SETNX 的方式存入 redis 中,並根據業務設定相應的超時時間;

  3. 如果設定成功,證明這是第一次請求,則執行後續的業務邏輯;

  4. 如果設定失敗,則代表已經執行過當前請求,直接返回。

 

 

 

欲把相思說似誰

          淺情人不知

 

 

 

 

相關文章