接口冪等性詳解

概述

所謂接口冪等性就是:在特定場景下,同一條件的多次接口調用,保證操作只執行一次,如果接口沒有保證冪等性,在以下場景就會產生問題

  • 前端重複提交:用戶進行註冊、創建個人信息等操作,由於網絡抖動導致頁面沒有及時響應,用戶認爲沒有成功而多次點擊提交按鈕,發生重複提交表單請求
  • 接口超時重試:提供外部系統調用的接口,因爲網絡抖動等原因執行成功但沒能及時響應,外部系統發起重試,導致重複調用
  • 消息重複消費:使用消息中間件時,消費者手動 ack 確認消息被正常消費時,消費者突然斷開連接,已經執行的消息會重新放回隊列,被其他消費者重新消費

如何實現接口冪等性?

1. 防重 Token 令牌

具體流程如下:

  • 客戶端獲取 token,服務端將 token 保存在 redis 中,token 需保證全局唯一
  • 之後客戶端發起請求時必須攜帶 token
  • 服務端校驗 token,如果成功則執行業務,並刪除 redis 中的 token,否則爲重複操作,直接返回結果

這種方式需保證同一請求都攜帶同一 token,比如同一訂單的支付操作都使用同一 token 請求。另外,在併發情況下,Redis 查找數據與刪除需要保證原子性,可以使用或 Lua 腳本保證

2. 使用 Redis 實現

這種實現方式是基於 redis 的 setnx 命令實現的,作用是如果 key 不存在,將 key 賦值爲 value 並返回 1,若 key 已存在,則不做操作並返回 0

具體流程如下:

  • 客戶端請求服務端,將能代表這次請求的唯一標識以 setnx 的方式存入 redis,並根據業務設置相應的超時時間
  • 如果設置成功,代表是第一次請求,執行後續業務邏輯
  • 如果設置失敗,代表已經執行過請求,直接返回

redis 是單線程的,所以不會有併發問題

3. 加鎖實現

具體流程如下:

  • 客戶端請求服務端,對能代表這次請求的唯一標識加鎖,保證同一時刻同一請求只有一個能被執行
  • 服務端根據唯一標識判斷是否第一次請求,比如查詢數據庫是否已存在該唯一標識的記錄,或者該唯一標識對應記錄狀態是否爲【已完成】
  • 如果是第一次請求,執行後續業務邏輯,否則直接返回

4. 冪等表

加鎖會影響性能,我們可以建一張冪等表,爲能代表這次請求的唯一標識建立唯一約束

具體流程如下:

  • 客戶端請求服務端,服務端會將本次請求的信息插入冪等表
  • 因爲有唯一約束,如果冪等表中不存在本次請求記錄,則插入成功,執行後續業務邏輯,插入失敗,則直接返回

使用這種方式,每次請求都會冪等表新建一條記錄,爲了避免表數據過大,可以定期進行清理,或者使用流水錶來代替冪等表。使用插入而不是查詢,也能有效避免併發問題

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章