系统设计中的幂等性

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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官…