浅谈网络中接口幂等性设计问题
所谓幂等性设计,就是说,一次和多次请求某一个资源应该具有同样的副作用。用数学的语言来表达就是:f(x) = f(f(x))。
在数学里,幂等有两种主要的定义。 在某二元运算下,幂等元素是指被自己重复运算(或对于函数是为复合)的结果等于它自己的元素。
某一元运算为幂等的时,其作用在任一元素两次后会和其作用一次的结果相同。
文章目录
- 一、关于幂等性
- 1、幂等的定义
- 2、幂等的必要性
- 3、幂等性
- 二、对于幂等性的实现
- 1、源头上--控制重复请求(前端防重)
- 2、过程上--过滤重复动作
- 3、结果上--解决重复写风险
一、关于幂等性
1、幂等的定义
所谓幂等性设计,就是说,一次和多次请求某一个资源应该具有同样的副作用。用数学的语言来表达就是:f(x) = f(f(x))。
下面是维基百科中对于幂等的定义:
在数学里,幂等有两种主要的定义。 在某二元运算下,幂等元素是指被自己重复运算(或对于函数是为复合)的结果等于它自己的元素。
某一元运算为幂等的时,其作用在任一元素两次后会和其作用一次的结果相同。
百度百科上是这么说的:
在编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。
幂等函数,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数。这些函数不会影响系统状态,也不用担心重复执行会对系统造成改变。
简而言之,幂等是指:多次调用方法或者接口不会改变业务状态,可以保证重复调用的结果和单次调用的结果一致。
2、幂等的必要性
根据上面对幂等性的定义我们得知:产生重复数据或数据不一致,这个绝大部分是由于发生了重复请求。
这里的重复请求是指同一个请求在一些情况下被多次发起。
在接口调用时一般情况下都能正常返回信息不会重复提交,不过在遇见以下情况时可能就会出现问题,如:
- 微服务架构下,不同微服务间会有大量的基于 http,rpc 或者 mq 消息的网络通信。如果超时了,微服务框架会进行重试;
- 用户交互的时候多次点击,无意地触发多笔交易;
- MQ消息中间件,消息重复消费;
- 第三方平台的接口(如:支付成功回调接口),因为异常也会导致多次异步回调;
- 其他中间件/应用服务根据自身的特性,也有可能进行重试。
举几个支付时的例子:
- 订单创建接口,第一次调用超时了,然后调用方重试了一次。是否会多创建一笔订单?
- 订单创建时,我们需要去扣减库存,这时接口发生了超时,调用方重试了一次。是否会多扣一次库存?
- 当这笔订单开始支付,在支付请求发出之后,在服务端发生了扣钱操作,接口响应超时了,调用方重试了一次。是否会多扣一次钱?
因为系统超时,而调用户方重试一下,会给我们的系统带来不一致的副作用。
3、幂等性
幂等性主要保证多次调用对资源的影响是一致的。其本质是通过唯一标识,标记同一操作的方式,来消除多次执行的副作用。
下一用 SQL DML 命令来理解幂等性操作:
- 查询(SELECT):查询语句不会对数据产生任何变化,天然具备幂等性;
- 新增(INSERT):带有唯一索引,重复插入会导致后续执行失败,具有幂等性;不带有唯一索引,多次插入会导致数据重复,不具有幂等性;
- 修改(UPDATE):直接赋值(score = 1),不管执行多少次 score 都一样,具备幂等性;计算赋值(score = score + 1),每次操作 score 数据都不一样,不具备幂等性;
- 删除(DELETE):绝对值删除(DELETE FROM … WHERE …),重复多次结果一样,具备幂等性;相对值删除(DELETE top(3) FROM …),重复多次结果不一致,不具备幂等性。
二、对于幂等性的实现
总的来说,我们解决幂等性问题就是要控制对资源的写操作,因此我们可以通过控制重复请求、过滤重复动作、解决重复写风险三种方式分别在源头、过程以及结果上对幂等性问题进行分析解决。
1、源头上–控制重复请求(前端防重)
通过前端防重保证幂等是最简单的实现方式,前端相关属性和JS代码即可完成设置。可靠性并不好,有经验的人员可以通过工具跳过页面仍能重复提交。主要适用于表单重复提交或按钮重复点击。
主要解决方案**:**
- 控制操作次数,例如:提交按钮仅可操作一次(提交动作后按钮置灰)
- 及时重定向,例如:下单/支付成功后跳转到成功提示页面,这样消除了浏览器前进或后退造成的重复提交问题。
2、过程上–过滤重复动作
# PRG 模式(前端)
PRG 模式即 POST-REDIRECT-GET。当用户进行表单提交时,会重定向到另外一个提交成功页面,而不是停留在原先的表单页面。这样就避免了用户刷新导致重复提交。同时防止了通过浏览器按钮前进/后退导致表单重复提交。 是一种比较常见的前端防重策略。
# 分布式锁
利用 Redis 记录当前处理的业务标识,当检测到没有此任务在处理中,就进入处理,否则判为重复请求,可做过滤处理。
订单发起支付时,支付系统先去 Redis 中查询是否存在该订单号的 Key。若不存在,则在 Redis 中新增这个Key。
接着查询订单是否已支付,若未支付,则支付完成后删除该订单的Key。
通过Redis做分布式锁,只有当一个请求执行完成后,才能执行下个请求。
# Token 机制实现
通过 Token 机制实现接口的幂等性,这是一种比较通用性的实现方法。
具体流程步骤:
- 客户端先发送一个请求去获取 Token,服务端会生成一个全局唯一的 ID 作为 Token 保存在 Redis 中,同时把这个 ID 返回给客户端;
- 客户端第二次调用业务请求的时候必须携带这个 Token;
- 服务端校验这个 Token,如果校验成功,则执行业务,并删除 Redis 中的 Token;
- 如果校验失败,说明 Redis 中已经没有对应的 Token,表示重复操作,直接返回指定的结果给客户端。
# 防重表
对于防止数据重复提交,还有一种解决方案就是通过防重表实现。防重表的实现思路也非常简单。首先创建一张表 作为防重表,同时在该表中建立一个或多个字段的唯一索引作为防重字段,用于保证并发情况下,数据只有一条。 在向业务表中插入数据之前先向防重表插入,如果插入失败则表示是重复数据。
- 对于防重表的解决方案,可能有人会说为什么不使用悲观锁。悲观锁在使用的过程中也是会发生死锁的。悲观锁是 通过锁表的方式实现的。 假设现在一个用户 A 访问表 A(锁住了表 A),然后试图访问表 B;
- 另一个用户 B 访问表 B(锁住了表 B),然后试图访问表 A。 这时对于用户 A 来说,由于表 B 已经被用户 B 锁住了,所以用户 A 必须等到用户 B 释放表 B 才能访问。 同时对于用户 B 来说,由于表 A 已经被用户 A 锁住了,所以用户 B 必须等到用户 A 释放表 A 才 能访问。此时死锁就已经产生了。
3、结果上–解决重复写风险
常见的方式有:悲观锁(for update)、乐观锁、唯一约束。
# 悲观锁
假设每一次拿数据,都有认为会被修改,所以给数据库的行或表上锁。
当数据库执行 select for update 时会获取被 select 中的数据行的行锁,因此其他并发执行的 select for update 如果试图选中同一行则会发生排斥(需要等待行锁被释放),因此达到锁的效果。
# 乐观锁
就是很乐观,每次去拿数据的时候都认为别人不会修改。更新时如果 version 变化了,更新不会成功。
缺点:就是在操作业务前,需要先查询出当前的 version 版本。
另外,还存在一种:状态机控制
例如:支付状态流转流程:待支付 -> 支付中 -> 已支付
具有一定要的前置要求的,严格来讲,也属于乐观锁的一种。
# 唯一约束
这种实现方式是利用 mysql 唯一索引的特性。
- 因为表中某个字段带有唯一索引,如果插入成功,证明表中没有这次请求的信息,则执行后续的业务逻辑;
- 如果插入失败,则代表已经执行过当前请求,直接返回。
相关文章:
浅谈网络中接口幂等性设计问题
所谓幂等性设计,就是说,一次和多次请求某一个资源应该具有同样的副作用。用数学的语言来表达就是:f(x) f(f(x))。 在数学里,幂等有两种主要的定义。 在某二元运算下,幂等元素是指被自己重复运算(或对于函数…...
《C Primer Plus》第13章复习题与编程练习
《C Primer Plus》第13章复习题与编程练习复习题1. 下面的程序有什么问题?2. 下面的程序完成什么任务?(假设在命令行环境中运行)3. 假设程序中有下列语句:4. 编写一个程序,不接受任何命令行参数或接受一个命…...
计算机SCI论文应该怎么作图? - 易智编译EaseEditing
计算机SCI论文,作图时要注意以下几个方面的问题: 1.图片的格式要tiff或者eps; 2.文件大小不能超过10M; 3.长和宽也给出了具体要求; 4.色彩模式要RGB或者灰度图; 5.文中的文字字体和大小; …...
【一】kubernetes集群部署
一、docker环境搭建 1、移除以前docker相关包 sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine2、配置yam源 sudo yum install -y yum-utilssudo yum-config-manager --ad…...
Docker安装Redis
一、拉取镜像 命令::docker pull <镜像名称>:<版本号> docker pull redis 二:Docker挂载配置文件 挂载:即将宿主的文件和容器内部目录相关联,相互绑定,在宿主机内修改文件的话也随之修改容…...
在shell中执行一条可执行程序(./a.out) 系统执行的过程
目录 系统调度过程 用户空间角度: 内核角度 1、调用fork创建一个新进程 2、使用_fo_fork创建新进程 3、父进程调用wake_up_new_task尝试唤醒新进程 4、CPU选择一个合适的进程来运行; 5、运行新进程 6、实现负载均衡 系统调度过程 分析在命令行…...
【ArcGIS Pro二次开发】(10):属性表字段(field)的修改
在ArcGIS Pro中,经常会遇到用字段计算器对要素的属性表进行计算。下面以一个例子演示如何在ArcGIS Pro SDK二次开发中实现。 一、要实现的功能 如上图所示的要素图层,要实现如下功能: 当字段【市级行政区】的值为【泉州市】时,将…...
数据结构与算法—散列表
目录 散列表 散列函数 散列冲突解决 1、开放寻址法 1.1 线性探测 1.2 二次探测 1.3 双重散列 2、链表法 使用场景 单词查找 散列表与链表的结合使用LRU 散列表总结 散列表实例 散列表 Word 单词拼写功能,如何实现的?散列表(Has…...
计算机网络笔记、面试八股(一)—— TCP/IP网络模型
本章目录1. TCP/IP网络模型1.1 应用层1.1.1 应用层作用1.1.2 应用层有哪些常用协议1.2 运输层1.2.1 TCP与UDP的区别1.2.2 分块传输1.2.3 端口1.3 网络层1.3.1 IP报文1.3.2 IP地址1.3.3 网络号和主机号的获得1.3.4 子网掩码的获得1.3.5 路由1.3.6 IP地址与MAC地址的区别1.3.7 AR…...
Servlet笔记(18):国际化
三个概念 国际化: 意义着一个网站提供不同版本的翻译成访问者的语言或国籍的内容。本地化: 意味着向网站添加资源,以使其适应特定的地理或文化区域。区域设置: 针对某个国家的某个地区的设置。 Servlet可以根据请求者的区域设置…...
kibana搭建(windowslinux)
1.说明 搭建kibana方便查询es库,本文分别对windows和linux版本进行安装,因为es集群版本是7.4.1,所以配套的kibana也是选择相同版本 2.下载 https://artifacts.elastic.co/downloads/kibana/kibana-7.4.1-windows-x86_64.zip https://artifact…...
(pytorch进阶之路)Informer
论文:Informer: Beyond Efficient Transformer for Long Sequence Time-Series Forecasting (AAAI’21 Best Paper) 看了一下以前的论文学习学习,我也是重应用吧,所以代码部分会比较多,理论部分就一笔带过吧 论文作者也很良心的…...
关键词聚类和凸现分析-实战1——亚急性甲状腺炎的
审稿人问题第8页第26行-请指出#是什么意思,并解释为什么亚急性甲状腺炎在这里被列为#8。我认为在搜索亚急性甲状腺炎相关文章时,关键词共现分析应该提供关键词共现的数据。这些结果的实际用途是什么?亚急性甲状腺炎是一种较为罕见但重要的甲状腺疾病&am…...
二叉树——二叉搜索树中的众数
二叉搜索树中的众数 链接 给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。 如果树中有不止一个众数,可以按 任意顺序 返回。 假定…...
安装_配置参数解读_集群安装配置_启动选举_搭建启停脚本---大数据之ZooKeeper工作笔记004
这里首先下载zookeeper安装包,可以看到官网地址 找到download 点击下载 找到老一点的,我们找3.5.7 in the archive 点击 然后这里找到3.5.7这一个 然后下载这个-bin.tar.gz这个...
RTMP的工作原理及优缺点
一.什么是RTMP?RTMP(Real-Time Messaging Protocol,实时消息传输协议)是一种用于低延迟、实时音视频和数据传输的双向互联网通信协议,由Macromedia(后被Adobe收购)开发。RTMP的工作原理是&#…...
【数据结构与算法】——第八章:排序
文章目录1、基本概念1.1 什么是排序1.2 排序算法的稳定性1.3 排序算法的分类1.4 内排序的方法2、插入排序2.1 直接插入排序2.2 直接插入排序2.3 希尔排序3、交换排序3.1 冒泡排序3.2 快速排序4、选择排序4.1 简单选择排序4.2 树形选择排序4.3 堆排序4.4 二路归并排序5、基数排序…...
在linux中web服务器的搭建与配置
以下涉及到的linux命令大全查阅 https://www.runoob.com/linux/linux-command-manual.htmlvim命令查阅 https://www.runoob.com/linux/linux-vim.htmlscp命令https://www.runoob.com/linux/linux-comm-scp.html首先要有一个请求的服务地址用ssh 进入到linux系统中ssh 请求的服务…...
《Python机器学习》基础代码2
👂 逝年 - 夏小虎 - 单曲 - 网易云音乐 目录 👊Matplotlib综合应用:空气质量监测数据的图形化展示 🌼1,AQI时序变化特点 🌼2,AQI分布特征 相关性分析 🌼3,优化图形…...
如何基于MLServer构建Python机器学习服务
文章目录前言一、数据集二、训练 Scikit-learn 模型三、基于MLSever构建Scikit-learn服务四、测试模型五、训练 XGBoost 模型六、服务多个模型七、测试多个模型的准确性总结参考前言 在过去我们训练模型,往往通过编写flask代码或者容器化我们的模型并在docker中运行…...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程
STM32F1 本教程使用零知标准板(STM32F103RBT6)通过I2C驱动ICM20948九轴传感器,实现姿态解算,并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化,适合嵌入式及物联网开发者。在基础驱动上新增…...
第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10+pip3.10)
第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10pip3.10) 一:前言二:安装编译依赖二:安装Python3.10三:安装PIP3.10四:安装Paddlepaddle基础框架4.1…...
Appium下载安装配置保姆教程(图文详解)
目录 一、Appium软件介绍 1.特点 2.工作原理 3.应用场景 二、环境准备 安装 Node.js 安装 Appium 安装 JDK 安装 Android SDK 安装Python及依赖包 三、安装教程 1.Node.js安装 1.1.下载Node 1.2.安装程序 1.3.配置npm仓储和缓存 1.4. 配置环境 1.5.测试Node.j…...
深入理解 React 样式方案
React 的样式方案较多,在应用开发初期,开发者需要根据项目业务具体情况选择对应样式方案。React 样式方案主要有: 1. 内联样式 2. module css 3. css in js 4. tailwind css 这些方案中,均有各自的优势和缺点。 1. 方案优劣势 1. 内联样式: 简单直观,适合动态样式和…...
大模型真的像人一样“思考”和“理解”吗?
Yann LeCun 新研究的核心探讨:大语言模型(LLM)的“理解”和“思考”方式与人类认知的根本差异。 核心问题:大模型真的像人一样“思考”和“理解”吗? 人类的思考方式: 你的大脑是个超级整理师。面对海量信…...
OPENCV图形计算面积、弧长API讲解(1)
一.OPENCV图形面积、弧长计算的API介绍 之前我们已经把图形轮廓的检测、画框等功能讲解了一遍。那今天我们主要结合轮廓检测的API去计算图形的面积,这些面积可以是矩形、圆形等等。图形面积计算和弧长计算常用于车辆识别、桥梁识别等重要功能,常用的API…...
