系統設計中的冪等性

1. 基本概念

冪等性(Idempotence)是系統設計中經常提到的概念。

如果某個操作執行一次或多次都能產生相同的結果,那么它就是冪等的

2. 代碼示例

下面這段代碼是冪等的。無論你調用多少次,show_my_button 的最終狀態都是False。

def hide_my_button(self):self.show_my_button = False

再看一個例子:

def toggle_my_button_visibility(self):self.show_my_button = not self.show_my_button

這個方法不是冪等的,因為每次調用都會翻轉狀態:第一次隱藏,第二次又顯示。

3. 常見誤區

3.1 冪等性與返回值無關

很多初學者會誤解冪等性,認為“多次調用返回值相同”才叫冪等。這是錯誤的,來看一個例子:

def hide_my_button(self):has_something_changed = self.show_my_buttonself.show_my_button = Falsereturn has_something_changed

如果第一次調用時 show_my_button 是 True,返回值是 True;再次調用時返回值變成了 False。但這個方法依然是冪等的,因為無論調用多少次,show_my_button 的最終狀態總是 False。冪等性關注的是操作的副作用或系統狀態的最終結果,而不是方法的返回值。

3.2 冪等與純函數

這兩個概念也容易混淆,所以簡單解釋一下。
純函數:給定相同的輸入,總是返回相同的輸出,且沒有任何副作用。

# 這是一個純函數。square(3) 將始終是相同的數字。
def square(my_number):return my_number ** 2# 這不是純函數。square(3) 幾乎不會產生相同的結果
def square_with_randomness(my_number):return (my_number ** 2) * random.uniform(0, 1)

冪等函數不一定是純函數。冪等函數可以有副作用:

# 如果每次保存相同的 name,最終數據庫的狀態保持一致 → 冪等
def save_name(name):my_database.save(name) # 寫入數據庫, 有副作用return name

4. 冪等性的問題

冪等設計也可能引入問題:如果某條“毒消息”導致消費者每次崩潰,那么該消息永遠留在隊列中。于是服務不斷重啟、崩潰、重試,形成死循環。
解決辦法:引入 死信隊列(DLQ),將處理失敗多次的消息轉移到 DLQ,以便后續人工排查。

5. 系統設計中的冪等性

在分布式系統中,網絡是不可靠的,服務會失敗,消息可能重復投遞,所以冪等性是保證數據一致性和系統健壯性的關鍵。以下場景都依賴冪等性:

  • 消息隊列的重復消費
  • RESTful API 請求重試
  • 數據庫寫入與 UPSERT
  • 分布式系統故障恢復
5.1 消息處理

假設我們有一個事件驅動系統:

  • Service A 往消息隊列里推送事件
  • Service B 消費這些事件(假設會執行一些計算操作)并寫入數據庫

如果Service B在計算過程中崩潰,或者Service B與數據庫之間存在網絡分區,或其他情況發生,那消息和事件將永遠丟失。

解決方案:不立即從隊列中刪除消息,而是等待Service B完成(包括寫入數據庫),然后再刪除消息。

但這帶來了一個新問題:同一條消息可能被讀取兩次。Service B執行計算并寫入數據庫,但隨后發生了一些情況(比如崩潰)。在消息從隊列中刪除之前,服務已經崩潰。會發生什么?當 Service B 重啟后,將繼續從最后那條消息開始消費,因此該消息被消費了兩次!但這并不成問題,如果 Service B 的處理邏輯是冪等的,那么即使消息被重復消費,最終結果也是一致的。

缺點是需要一些額外的復雜性(需要保證操作冪等)和一些計算資源(可能不必要地多次執行相同操作)。但這些缺點和丟失消息比起來不值一提。

5.2 API

如果你正在構建REST API,其實已經在處理冪等性了。HTTP協議實際上定義了哪些方法應該是冪等的:

HTTP 方法冪等性說明
GET查詢資源,多次調用結果相同
PUT完全替換資源,重復 PUT 沒有副作用
DELETE刪除資源,刪除已不存在的資源結果也相同
POST通常用于創建資源,天然非冪等

POST請求:通常在設計上不是冪等的。每個POST通常創建某些內容。但你可以使用冪等鍵使它們冪等。其工作原理如下:隨請求發送一個唯一ID(通常在頭中),服務器記住"已經處理過這個ID,因此將返回相同的結果,而不是再次執行工作"。

def create_user(request):idempotency_key = request.headers.get('Idempotency-Key')# 是否已經處理過這個確切的請求?if idempotency_key and already_processed(idempotency_key):return get_cached_response(idempotency_key)# 沒有,創建用戶user = User.create(request.data)# 緩存響應以備下次使用if idempotency_key:cache_response(idempotency_key, user)return user
5.3 數據庫

在數據庫操作中,常用的冪等性設計包括:

UPSERT操作(如果存在則INSERT或UPDATE)自然是冪等的。使用相同數據運行update 10次,每次都會得到相同的結果。記錄要么創建一次,要么多次更新為相同的值。

5.4 分布式系統

在分布式系統中,冪等性是重試機制的安全基礎。

  • 網絡調用失敗可能導致請求被重發
  • 微服務之間的鏈路存在超時重試
  • 跨機房、跨服務調用可能會收到重復事件

如果操作不是冪等的,每次重試可能引入數據污染和狀態異常。

6. 完整示例:訂單處理系統

下面通過一個具體示例將所有內容整合起來。有一個簡單的訂單處理流水線:訂單來自Web應用程序,由訂單服務驗證,進入隊列,然后由訂單處理器服務處理并寫入數據庫。

  • Web App → 提交訂單請求
  • API Gateway → 路由、鑒權、限流
  • Order Service → 校驗訂單并發送消息到 MQ
  • MQ → 存儲訂單消息
  • Order Processor Service → 消費消息并寫入數據庫
  • Orders DB → 持久化訂單數據
  • Dead-Letter Queue → 收集失敗的消息
  • Notification Service → 給用戶發送通知

這里的關鍵是 Order Service 要是冪等的。怎么使Order Service冪等?

Order Service從 MQ 消費消息并執行實際的業務邏輯。當處理消息(即訂單事件)時,我們希望:

  1. 檢查它是否已被處理
  2. 如果沒有,將其插入Orders DB,告知Notification Service發送通知

這是冪等的,因為已經檢查它是否已被處理。可以通過在訂單表中執行SELECT操作,僅當不存在時才插入。可以對通知服務執行類似操作,或在通知服務內部使用其自己的數據庫執行。

注意需要處理并發問題(有兩個不同的訂單處理服務實例處理同一條消息,并且它們同時執行SELECT),處理消息兩次不是一個合理的做法,更好的方案是將此邏輯包裝到事務中。

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

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

相關文章

Pandas vs Polars Excel 數據加載對比報告

?? Pandas vs Polars Excel 數據加載對比報告 1. 數據基本情況 數據文件:data.xlsx 數據規模:23,670 行 3 列 字段: case_time:日期/時間 case_name:公司名稱(字符串) board:所屬板塊(字符串) 2. 加載方式與代碼 Pandas import pandas as pdfrom tools import…

Kafka 為什么具有高吞吐量的特性?

Kafka 高吞吐量原因:面試題總結 在面試中,Kafka 的高吞吐量設計是高頻考點,核心需圍繞“架構設計”“存儲優化”“網絡效率”“資源利用”四個維度展開,以下是結構化總結: 一、核心架構:并行化與分層設計分…

MCP 協議原理與系統架構詳解—從 Server 配置到 Client 應用

1. MCP MCP(Model Context Protocol,模型上下文協議)是開發 Claude 模型的(Anthropic)公司推出的一個開放標準協議,就像是一個 “通用插頭” 或者 “USB 接口”,制定了統一的規范,不管是連接數據庫、第三方…

uniapp安卓真機調試問題解決總結

uniapp安卓真機調試遇到各種連接不上問題: 手機上打開調試數據線不行,換數據線電腦重啟手機重啟拔出數據線,換個USB插口。

Linux Qt創建和調用so庫的詳細教程

一、創建so庫1.文件-->新建文件或項目-->Library->C Library,如下圖2.工程命名為Example3.一直下一步就可以4、工程創建完成,如下圖5、刪除Example_global.h6、配置.pro文件# 設置輸出目錄 DESTDIR $$PWD/output #只生成.so文件 CONFIG plugi…

【深度學習】蒙特卡羅方法:原理、應用與未來趨勢

作者選擇了由 Ian Goodfellow、Yoshua Bengio 和 Aaron Courville 三位大佬撰寫的《Deep Learning》(人工智能領域的經典教程,深度學習領域研究生必讀教材),開始深度學習領域學習,深入全面的理解深度學習的理論知識。 之前的文章參考下面的鏈接&#xf…

區塊鏈技術原理(18)-以太坊共識機制

文章目錄前言什么是共識?什么是共識機制?共識機制的核心目標共識機制的類型PoW(工作量證明)協議:(2015-2022)PoS(權益證明)協議:(PoS,…

java基礎(十五)計算機網絡

網絡模型概述 為了使得多種設備能通過網絡相互通信,并解決各種不同設備在網絡互聯中的兼容性問題,國際標準化組織(ISO)制定了開放式系統互聯通信參考模型(OSI模型)。與此同時,TCP/IP模型作為實際…

idea將服務封裝為一個jar包

你使用的是 IntelliJ IDEA 2018,這個版本雖然不是最新的,但完全支持通過 圖形化界面 打 JAR 包(無需命令行),非常適合你在公司內部將 Snowflake 模塊打包成通用組件。下面我將 手把手、一步一步、圖文流程式地教你&…

ZYNQ [Petalinux的運行]

一、下載ubuntu 下載地址很多,這里提供了一個:http://mirrors.aliyun.com/ubuntu-releases/14.04/ 推薦開始瀏覽器下載之后復制下載鏈接使用迅雷下載。 二、虛擬機安裝Ubuntu vmware中安裝Ubutun–這部分不展示 安裝ssh sudo apt install openssh-s…

excel 破解工作表密碼

破解Excel工作表密碼可通過易用寶工具、VBA腳本或修改文件格式實現,具體方法需根據文件類型和密碼保護類型選擇。 ?使用易用寶工具(推薦)? 適用于Excel 2007及以上版本,操作簡便且無需編程基礎: 下載安裝Excel易用…

Deepseek + RAGFlow 搭建本地知識庫問答系統

Deepseek RAGFlow 搭建本地知識庫問答系統原因為什么要本地部署RAG模型和微調模型區別本地部署流程1. 下載 ollama ,通過ollama把Deepseek模型下載到本地運行。2. 下載RAGFlow 源代碼和 Docker ,通過Docker部署RAGFlow。3. 在RAGFlow中構建個人知識庫并…

elementui附件上傳自定義文件列表,實現傳完即可預覽、下載、刪除,二次封裝el-upload

背景當前 elementui 的文件上傳組件在上傳完文件之后只支持刪除,用戶希望可以看到附件信息,還可以預覽自己剛剛上傳但未提交的文件,還希望可以下載,因為公司的下載功能當前是通過 OnlyOffice 實現了文件格式轉換,所以我…

linux的conda配置與應用階段的簡單指令備注

1.新建某虛擬環境 conda create -n 虛擬環境名 pythonPython版本號 (-y)2.退出當前虛擬環境 conda deactivate3.查看當前conda環境下所有的虛擬環境 conda info --envs4.查看conda版本和位置 conda --versionwhich conda5.激活某個conda虛擬環境 conda activate 虛擬環境名

虛擬化技術 ——KVM

一、KVM 技術簡介 KVM(Kernel-based Virtual Machine,基于內核的虛擬機)是 Linux 內核原生支持的全虛擬化解決方案,依托 CPU 的硬件虛擬化技術(Intel VT-x/AMD-V)實現高效的虛擬機運行。它將 Linux 內核轉…

線程間Bug檢測工具Canary

Canary1.Introduction2.Approach2.1.數據依賴分析2.2.線程間依賴分析3.Bug檢測4.Evaluation參考文獻1.Introduction 主要做跨線程value-flow bug檢查,下面代碼中兩個函數中存在指向關系:1. x→o1x \rightarrow o_1x→o1?, b→o2b \rightarrow o_2b→o2…

AEB 強制來臨,東軟睿馳Next-Cube-Lite有望成為汽車安全普惠“破局器”

AEB 強制時代正在悄然譜寫“普惠安全”的行業底色。日前,備受關注的強制性國家標準《輕型汽車自動緊急制動系統技術要求及試驗方法》(以下簡稱“新國標”)意見征求階段已經結束。該標準將替代現行國標GB/T 39901-2021,計劃于2028年…

css的white-space: pre

用戶從別的地方復制的配置文件,粘貼到輸入框內,需要保留原始格式發送給后端。核心步驟:### 1. 格式保持機制 - white-space: pre :這是最關鍵的CSS屬性,確保所有空格、制表符、換行符都被保留 - wrap"off" &…

【AI解讀源碼系列】ant design mobile——Space間距

前言 筆者目前業務主要圍繞ant design mobile組件庫來交付H5前端工作。 故此出此專欄來解讀每一個組件是如何實現的。 本文基于AI來解讀Space組件。 文檔鏈接: https://mobile.ant.design/zh/components/space 源碼: https://github.com/ant-design/ant-…

《用餐》,午餐食堂即景小詩分享(手機/小視頻/光盤/養生)

大媽食堂碎碎念,怪罪手機延工期。 筆記模板由python腳本于2025-08-21 19:34:46創建,本篇筆記適合喜歡友善生活和詩的coder翻閱。 學習的細節是歡悅的歷程 博客的核心價值:在于輸出思考與經驗,而不僅僅是知識的簡單復述。 Python官…