接口等冪處理

介紹

? 什么是等冪(Idempotency)?

等冪

無論這個操作被執行多少次,結果都是一樣的,不會因為多次執行而產生副作用。

通俗一點說:“點一次和點一百次,效果是一樣的。”

? 在接口中,什么是等冪操作?

在 Web / API 開發中,一個 等冪操作的接口,意味著客戶端(用戶、服務、瀏覽器)多次請求同一個接口,結果不變,也不會影響系統的狀態或數據重復修改。

操作等冪性原因
GET /user/123? 是多次獲取用戶信息不改變任何東西
DELETE /user/123? 是刪除一次和刪除多次效果一樣,用戶都不存在
PUT /user/123 {name: “Tom”}? 是每次更新為相同數據,結果一樣
POST /user? 否每次都會新建一個用戶,重復多次會創建多個資源
?	PUT 是等冪的,因為它是“更新為某個狀態”
?	POST 不是等冪的,因為它每次都是“創建新的資源”

? 為什么等冪很重要?

? 防止重復扣款、重復下單、重復刪除等問題;

? 支持客戶端/中間代理的自動重試;

? 提高系統容錯能力。

? 如何實現接口等冪?

常見做法有:

  1. 冪等鍵(Idempotency Key):客戶端每次請求都帶上一個唯一 key,服務端緩存這個 key,避免重復處理。例如支付場景就常用這個機制。

  2. 根據業務設計邏輯保證冪等:比如數據庫 INSERT 改為 UPSERT(存在則更新,不存在則插入)。

  3. 冪等性中間件 / 請求鎖定機制:防止重復請求在短時間內被處理多次。

處理PUT的等冪

多次調用會修改 update_time、產生日志、觸發 webhook、更新緩存等等副作用。

理論上:

? PUT /resource/123 的語義是:把這個資源更新成某個固定狀態

? 所以連續多次執行 PUT(用相同數據),最終資源狀態是一致的 —— 這是“等冪”。

實際上:

? 即使數據一樣,每次 PUT 可能都會執行:

? 自動更新時間戳(update_time)

? 寫數據庫變更日志

? 寫操作審計表

? 發送消息到 MQ

? 清理或更新緩存

? 這些副作用就

破壞了等冪性

👉 方式一:判斷數據是否變更

if new_data != old_data:do_update()

? 如果數據一樣,直接跳過寫入、跳過更新時間戳等

? 這種方式最簡單,適合“頻繁重復 PUT”的場景。

👉 方式二:允許更新,但保持副作用冪等

? 比如:

? update_time 只在數據真正變更時更新;

? 日志、MQ 消息僅在內容變更時才觸發;

? 或使用冪等鎖 + 緩存處理。

👉 方式三:使用冪等 key(更適合 POST)

比如前端在 10s 內重試,帶上冪等 key,服務端只處理一次。

? 針對 update_time 的建議做法:

def update_user(user_id, new_data):old_data = db.get_user(user_id)if new_data == old_data:return  # 數據沒變,不做更新new_data["update_time"] = now()db.update_user(user_id, new_data)

冪等鎖+緩存處理

這是用于更復雜、可能存在并發請求前端重復請求場景的策略。

📌 場景:

假設你的接口會被短時間內 多次調用(并發 or 重試)

PUT /order/123/status {"status": "paid"}

應該避免:

?	用戶一不小心連點了 2 次;
?	前端接口設置了“自動重試機制”;
?	網關/中間層產生了重復調用。

? 解決方式:使用「冪等鎖」

  1. 給每次請求生成一個冪等 key(比如前端傳遞一個唯一 idempotent-key);

  2. 使用緩存(Redis)記錄這個 key 的處理狀態

  3. 判斷是否已經處理過,如果是,就跳過執行邏輯。

# 接收到請求
key = f"idempotent:{user_id}:{operation_id}"
if redis.exists(key):return "已處理,直接返回"# 設置鎖,有效期60秒
redis.set(key, "processing", ex=60)try:# 執行更新操作db.update_order_status("paid")mq.send("order.paid")write_log("用戶付款成功")
finally:redis.delete(key)

等冪鎖流程

? 冪等鎖的完整流程設計(前后端協作)

🔸 適用場景:

? 用戶發起重要操作,如:下單、支付、扣積分、修改狀態

? 你希望避免:

? 用戶手抖點兩下

? 前端接口自動重試

? 網關中轉多次

? 并發執行相同邏輯導致“重復創建 / 重復扣款”

? 正確的冪等鎖邏輯應該是:

? 「令牌模式」冪等方案

后端生成 冪等 key,前端持有這個 key,之后帶著這個 key 去執行冪等請求。

模式說明適合場景
令牌模式前端先拿一個冪等 key(令牌),再帶著 key 去調接口用戶主動操作型,如“提交訂單”
前端生成UUID前端自己生成 UUID,當做冪等 key 發請求自動重試 / 服務間調用 場景

令牌方式:

?	冪等 key 生命周期完全由后端掌控 ?;
?	安全性高,不依賴前端生成 uuid 的正確性 ?;
?	能配合業務類型(如創建訂單、支付、退款)做細粒度控制 ?;
?	可以直接緩存執行結果,實現「重復請求 → 直接返回結果」 ?;
維度你說的方式(后端生成)之前的方式(前端生成)
控制權在后端 ?在前端 ?
安全性更高 ?依賴前端或外部系統
結果緩存容易實現 ?實現麻煩 ?
實現復雜度多一步(key申請)略簡單
應用場景提交表單、支付類接口微服務調用、冪等補償邏輯

冪等令牌機制”,非常適合處理「用戶主動操作 + 嚴格控制重復」的接口,強烈推薦在 支付、下單、扣款等業務中使用。

注意:

? 前端生成 UUID 并不是簡單「純隨機」,它要遵循 可識別性可復用性 的規則,才能讓后端識別同一個操作。

? 正確的前端 UUID 冪等 key 設計方案

🔸 前提場景適用:

? 后端不參與冪等 key 生成(例如微服務架構中,一些服務沒有共享 Redis)

? 前端或調用方能控制 key 生成(如 App / 網關 / API 調用方)

? 通常用于:接口重試、任務去重、上傳文件避免重復入庫等

需要生成的 UUID 實際是“結構化唯一 key”,并不是完全隨機,比如:

idempotent:<業務類型>:<用戶ID>:<業務ID或時間戳>
業務場景冪等 key 示例
下單idemp:order:uid123:order456
修改用戶信息idemp:user:update:uid123
提交問卷idemp:survey:uid123:survey_20240330
提交任務(時間窗口內)idemp:task:uid123:20240330T10
Key 設計是否推薦原因
完全隨機 UUID? 不推薦后端無法判斷是否是重復操作
帶業務結構的 key? 推薦可以判斷“是不是相同操作”
后端統一分發 key? 更推薦更安全、更集中控制

?

與其在前端搞業務 ID / 時間戳構造 key,不如直接用令牌機制:后端統一生成并下發冪等 key,前端拿著用。

對比點時間戳方案(前端方案)令牌機制(后端)
冪等 key 來源前端生成時間戳后端統一生成
是否真正冪等? 多次執行都不同? 同一個 key 保證只執行一次
是否能緩存結果? 難以復用? 可直接返回上次執行結果
實現復雜度中(要設計 key 格式)高一點(需要額外接口)
安全性 & 可控性? 前端失控? 后端控制

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/75049.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/75049.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/75049.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

P1090合并果子(優先隊列)

洛谷題目 這里使用的是優先隊列&#xff0c;非常簡單 首先讓我們一起來學習一下優先隊列&#xff08;默認是從大到小來排列&#xff09; 首先要使用頭文件 #include<queue> using namespace std; 然后聲明有限隊列 priority_queue<int> a; priority_queue&…

藍橋杯備考---->并查集之 Lake Counting

這道題就統計有多少個連通塊就行了 這時候我們又需要把二維轉成一維了&#xff0c;也就是把每一個格子都給一個編號 當我們合并連通塊的時候&#xff0c;其實是只需要四個方向的 因為我們是從上往下遍歷的&#xff0c;我們遍歷到某個位置的時候&#xff0c;它已經和上面部分…

React受控表單綁定

受控表單綁定 在 React 中&#xff0c;受控組件&#xff08;Controlled Component&#xff09;是指表單元素的值由 React 組件的 state 管理&#xff0c;React 通過 onChange 事件監聽輸入變化&#xff0c;并實時更新 state&#xff0c;從而控制表單輸入值。 為什么要使用受控…

8、linux c 信號機制

一、信號概述 1. 信號概念 信號是一種在軟件層次上對中斷機制的模擬&#xff0c;是一種異步通信方式。信號的產生和處理都由操作系統內核完成&#xff0c;用于在進程之間傳遞信息或通知某些事件的發生。 2. 信號的產生 信號可以通過以下方式產生&#xff1a; 按鍵產生&…

CSP-J 2019 入門級 第一輪(初賽) 完善程序(2)

【題目】 CSP-J 2019 入門級 第一輪&#xff08;初賽&#xff09; 完善程序&#xff08;2&#xff09; &#xff08;計數排序&#xff09;計數排序是一個廣泛使用的排序方法。下面的程序使用雙關鍵字計數排序&#xff0c;將n對10000 以內的整數&#xff0c;從小到大排序。 例如…

Vue3 項目通過 docxtemplater 插件動態渲染 .docx 文檔(帶圖片)預覽,并導出

Vue3 項目通過 docxtemplater 插件動態渲染 .docx 文檔&#xff08;帶圖片&#xff09;預覽&#xff0c;并導出 預覽安裝插件示例代碼項目目錄結構截圖實際效果截圖 動態渲染 .docx 文檔&#xff08;帶圖片&#xff09;&#xff0c;預覽、導出安裝插件docx 模板文件內容完整代碼…

養老更安心!智紳科技“智慧”養老系統,智在何處?

在老齡化趨勢不斷加劇的當下&#xff0c;養老問題成為全社會關注的焦點。 人們對于養老服務的需求日益增長&#xff0c;不僅期望能夠得到基本的生活照料&#xff0c;更渴望在安全、舒適、便捷的環境中安享晚年。 智紳科技的“智慧”養老系統應運而生&#xff0c;憑借其獨特的…

MySQL 當中的鎖

MySQL 當中的鎖 文章目錄 MySQL 當中的鎖MySQL 中有哪些主要類型的鎖&#xff1f;請簡要說明MySQL 的全局鎖有什么用&#xff1f;MySQL 的表級鎖有哪些&#xff1f;作用是什么&#xff1f;元數據鎖&#xff08;MetaData Lock&#xff0c;MDL&#xff09;意向鎖&#xff08;Inte…

vue前端代碼作業——待辦事項

美化樣式示意圖&#xff1a; 后端IDEA代碼示意圖&#xff1a; 代碼解釋&#xff1a; 1. isAllChecked 計算屬性的作用 isAllChecked 用于實現 “全選 / 全不選” 功能&#xff0c;它是一個 雙向綁定 的計算屬性&#xff08;因為 v-model 需要同時支持讀取和設置值&#xff09…

Oracle數據庫數據編程SQL<3.1 PL/SQL 匿名塊 及 流程控制中的條件判斷、循環、異常處理和隨機函數應用>

PL/SQL部分 在SQL的基礎上增加了一些過程化的控制語句。 過程化控制語句包括&#xff1a;類型定義、判斷、循環、游標、異常處理&#xff08;例外處理&#xff09; 目錄 PL/SQL匿名塊 一、匿名塊基本結構 1、匿名塊由三個部分組成&#xff1a; 2、注意事項&#xff1a; …

DeepSeek詳解:探索下一代語言模型

文章目錄 前言一、什么是DeepSeek二、DeepSeek核心技術2.1 Transformer架構2.1.1 自注意力機制 (Self-Attention Mechanism)(a) 核心思想(b) 計算過程(c) 代碼實現 2.1.2 多頭注意力 (Multi-Head Attention)(a) 核心思想(b) 工作原理(c) 數學描述(d) 代碼實現 2.1.3 位置編碼 (…

Git Reset 命令詳解與實用示例

文章目錄 Git Reset 命令詳解與實用示例git reset 主要選項git reset 示例1. 撤銷最近一次提交&#xff08;但保留更改&#xff09;2. 撤銷最近一次提交&#xff0c;并清除暫存區3. 徹底撤銷提交&#xff0c;并丟棄所有更改4. 回退到特定的提交5. 取消暫存的文件 git reset 與 …

前端知識點---事件監聽器里面的e.target跟this的區別,e.target在事件委托中的好處

文章目錄 ? 相同點? 不同點? 總結區別e.target與事件委托之間的關系 在事件監聽器中&#xff0c;e.target 和 this 有時是一樣的&#xff0c;但它們并不完全相同。 ? 相同點 當事件直接綁定到元素時&#xff1a; e.target 和 this 通常指向相同的元素&#xff0c;即事件綁…

Elasticsearch 完全指南

1. Elasticsearch基礎知識 1.1 什么是Elasticsearch Elasticsearch是一個基于Lucene的分布式、RESTful風格的搜索和數據分析引擎。它是一個開源的、高擴展的、分布式的全文搜索引擎,可以近乎實時地存儲、檢索數據。 Elasticsearch不僅僅是一個全文搜索引擎,它還可以用于以…

Python 3 與 MySQL 數據庫連接:mysql-connector 模塊詳解

Python 3 與 MySQL 數據庫連接&#xff1a;mysql-connector 模塊詳解 概述 在Python 3中&#xff0c;與MySQL數據庫進行交互是一個常見的需求。mysql-connector是一個流行的Python模塊&#xff0c;它提供了與MySQL數據庫連接和交互的接口。本文將詳細介紹mysql-connector模塊…

SQL:CASE WHEN使用詳解

文章目錄 1. 數據轉換與映射2. 動態條件篩選3. 多條件分組統計4. 數據排名與分級5. 處理空值與默認值6. 動態排序 CASE WHEN 語句在 SQL 中是一個非常強大且靈活的工具&#xff0c;除了常規的條件判斷外&#xff0c;還有很多巧妙的用法&#xff0c;以下為你詳細總結&#xff1a…

【字符設備驅動開發–IMX6ULL】(二)Linux 設備號

【字符設備驅動開發–IMX6ULL】&#xff08;二&#xff09;Linux 設備號 文章目錄 【字符設備驅動開發–IMX6ULL】&#xff08;二&#xff09;Linux 設備號1 設備號的組成2.設備號的分配 1 設備號的組成 為了方便管理&#xff0c;Linux 中每個設備都有一個設備號&#xff0c;設…

【字符設備驅動開發–IMX6ULL】(一)簡介

【字符設備驅動開發–IMX6ULL】&#xff08;一&#xff09;簡介 一、Linux驅動與裸機開發區別 1.裸機驅動開發回顧 ? 1、底層&#xff0c;跟寄存器打交道&#xff0c;有些MCU提供了庫。 spi.c&#xff1a;主機驅動&#xff08;換成任何一個設備之后只需要調用此文件里面的…

YOLOv8+ Deepsort+Pyqt5車速檢測系統

該系統通過YOLOv8進行高效的目標檢測與分割&#xff0c;結合DeepSORT算法完成目標的實時跟蹤&#xff0c;并利用GPU加速技術提升處理速度。系統支持模塊化設計&#xff0c;可導入其他權重文件以適應不同場景需求&#xff0c;同時提供自定義配置選項&#xff0c;如顯示標簽和保存…

藍橋杯嵌入式學習筆記

用博客來記錄一下參加藍橋杯嵌入式第十六屆省賽的學習經歷 工具環境準備cubemx配置外部高速時鐘使能設置串口時鐘配置項目配置 keil配置燒錄方式注意代碼規范頭文件配置 模塊ledcubemx配置keil代碼實現點亮一只燈實現具體操作的燈&#xff0c;以及點亮還是熄滅 按鍵cubemx配置k…