樂觀鎖實現介面冪等性 支援API冪等操作

2021-10-16 14:45:33 字數 1412 閱讀 8977

背景

平台有部分 api 需要保證介面冪等性, 防止業務頻繁刷 api 造成資源浪費,或者不小心重發訊息影響業務。

名詞解釋

介面的冪等, 指的是乙個操作重複執行n次得到的結果(***)與執行一次是相等的。比如在 http 協議中,get請求,會得到同樣的資料。但是對於 post 和 patch 的介面, 每次請求動作得到結果都是不同, 這裡是不冪等的, 而有的是時候對介面有冪等的要求。

比如銀行的轉賬, 由於各種原因可能同乙個請求會被多次傳送,但是結果只會成功轉賬一次,其他轉賬不會生效。

解決方案

目前業界有相對成熟的解決方案, 包括 悲觀鎖,樂觀鎖,防重表和使用 token。下面分別介紹以上4種解決方案。

悲觀鎖流程:請求過來的時候開啟事務, 對查詢事件(比如訂單)加鎖

判斷事件是否符合執行條件

在全部執行完後, 提交或回滾

缺點: 執行時間長, 悲觀鎖容易鎖住整表,導致服務不可用問題。

樂觀鎖實現:通過版本號的方式,在更新事件的時候鎖表 (大部分時間不會鎖表), 比如:update table set usage=usage+1, version=version+1 where uuid = *** and version = ***

即使多個請求過來, 因為進來的 version 是相同的, 但是 db 中的版本號已經被更新, 修改條件不成立, 也就是說不會被多次更新。

缺點: 使用 主鍵 或 唯一索引 來更新, 使用行鎖而不是表鎖。

防重表流程:建立一張防重表, 使用事件 id (比如訂單號) 作為唯一索引

在發起請求時根據事件 id 在 防重表 中新增一條記錄

因為是唯一索引,重發的請求新增記錄不會成功, 第乙個進入的事件可以被執行(事件完成後,可以刪除防重表的記錄)

缺點:多維護一張資料表,增加業務邏輯複雜度。

使用 token

流程:業務方在呼叫 api 的時候, 在 header 裡傳遞乙個 x-request-id 引數(隨機 id, 類似 token)

平台接收到這次請求, 判斷在快取裡是否存在對應 x-request-id 對應的記錄:如果記錄存在, 表明這條訊息已經被傳送過, 介面返回 http 412 code

如果記錄不存在, 將該記錄刷到快取裡, 傳送訊息

response 的 header 也返回 x-request-id

缺點:流程比防重表更複雜。

冪等性優缺點

優點:實現介面的冪等性

不需要關心隨機 id 的業務邏輯

缺點:增加了實現的複雜度

增加運維成本

總結基於我們當前的業務現狀,使用 x-request-id + 快取來支援訊息 api 的冪等操作。雖然方案依賴 redis, 但是平台本身就有使用快取, 運維成本這個缺點可忽略不計, 邏輯實現相對簡單。 綜上可以設施。

參考

樂觀鎖的冪等性方案

那麼為了使用樂觀鎖,我們首先修改t goods表,增加乙個version欄位,資料預設version值為1。update t goods set count count 1 version version 1 where good id and version 1 根據version版本,也就是在操...

介面冪等性

例如 在http協議中,get請求,會得到同樣的資料 bool get money id,amount 1引數 id 使用者的賬戶 amount 表示取多少錢 返回值 true 表示取錢成功 false 表示取錢失敗 情景一 1 一位使用者a 取100塊錢,這個請求,傳送到了伺服器 2 伺服器正常的...

介面冪等性

token機制 服務端提供傳送token的介面,在分析業務的時候,哪些業務是存在冪等問題的,就必須在執行業務前,先去獲取token,伺服器會把token儲存到人redis中 然後呼叫業務介面請求時,把token攜帶過去,一般放在請求頭 伺服器判斷token是否存在redis中,存在表示第一次請求,然...