接口幂等性是什么?如何设计?

article/2025/10/3 16:04:17

接口幂等

  • 什么是接口幂等?
  • 为什么接口需要幂等性设计
    • 前端重复提交表单
    • 黑客恶意攻击
    • 接口超时重复提交
    • 消息重复消费
  • 哪些接口需要幂等?
  • 如何实现幂等
    • 前端拦截
    • 数据库唯一索引实现
    • 数据库乐观锁实现
    • 数据库悲观锁实现
    • JVM锁实现
    • 分布式锁实现
    • Token实现
  • 总结

接口幂等-幂等性-接口的幂等性-分布式幂等性-如何保证幂等-幂等性实现方案-去重表-下单幂等-支付幂等-扣还库存幂等

什么是接口幂等?

在计算机中编程中,一个幂等操作的特点是其任意多次执行所产生的影响均与第一次执行的影响相同。

接口的幂等性实际上就是接口可重复调用,在调用方多次调用的情况下,接口最终得到的结果是一致的。有些接口可以天然的实现幂等性,比如查询接口,对于查询来说,你查询一次和两次,对于系统来说,没有任何影响,查出的结果也是一样。

为什么接口需要幂等性设计

该问题等同于 为什么会重复调用?

前端重复提交表单

在填写一些表格时候,用户填写完成提交,很多时候会因网络波动没有及时对用户做出提交成功响应,致使用户认为没有成功提交,然后一直点提交按钮,这时就会发生重复提交表单请求。

黑客恶意攻击

例如在实现用户投票这种功能时,如果黑客针对一个用户进行重复提交投票,这样会导致接口接收到用户重复提交的投票信息,这样会使投票结果与事实严重不符。

接口超时重复提交

大部分RPC框架[比如Dubbo],为了防止网络波动超时等造成的请求失败,都会添加重试机制,导致一个请求提交多次。

消息重复消费

当使用 MQ 消息中间件时候,如果Consumer消费超时或者producer发送了消息但由于网络原因未收到ACK导致消息重发,都会导致重复消费。

哪些接口需要幂等?

幂等性的实现与判断需要消耗一定的资源,因此不应该给每个接口都增加幂等性判断,要根据实际的业务情况和操作类型来进行区分。例如,我们在进行查询操作和删除操作时就无须进行幂等性判断。查询操作查一次和查多次的结果都是一致的,因此我们无须进行幂等性判断。删除操作也是一样,删除一次和删除多次都是把相关的数据进行删除(这里的删除指的是条件删除而不是删除所有数据),因此也无须进行幂等性判断。

所以到底哪些接口需要幂等?关于这个问题需要从具体业务出发,但是也有规律可循如下表:

接口类型是否幂等描述
GETGet方法用于获取资源。其一般不会也不应当对系统资源进行改变,所以是幂等的。
POST×Post方法一般用于创建新的资源。其每次执行都会新增数据,所以不是幂等的。
PUT-Put方法一般用于修改资源。该操作则分情况来判断是不是满足幂等,更新操作中直接根据某个值进行更新,也能保持幂等。不过执行索加操作的更新是非幂等。
DELETE-Delete方法一般用于删除资源。该操作则分情况来判断是不是满足幂等,当根据唯一值进行删除时,删除同一个数据多次执行效果一样。不过需要注意,带查询条件的删除则就不一定满足幂等了。例如在根据条件删除一批数据后,这时候新增加了一条数据也满只条件,然后又执行了—次删除,那么将会导致新增加的这条满足条件数据也被删除。

如何实现幂等

前端拦截

前端拦截是指通过 Web 站点的页面进行请求拦截,比如在用户点击完“提交”按钮后,我们可以把按钮设置为不可用或者隐藏状态,避免用户重复点击。

该方法可以解决用户误操作提交两次表单所产生的重复提交问题。但前端拦截有一个致命的问题,如果是懂行的程序员或者黑客可以直接绕过页面的 JS 执行,直接模拟请求后端的接口,这样的话,我们前端的这些拦截就不能生效了。因此除了前端拦截一部分正常的误操作之外,后端的验证必不可少。

数据库唯一索引实现

数据库唯一索引实现方案一般只能适用于执行插入操作的过程。
在这里插入图片描述
具体流程步骤:

  • 建立一张去重表,其中某个字段需要建立唯一索引
  • 客户端去请求服务端,服务端会将这次请求的一些信息插入这张去重表中
  • 因为表中某个字段带有唯一索引,如果插入成功,证明表中没有这次请求的信息,则执行后续的业务逻辑
  • 如果插入失败,则代表已经执行过当前请求,直接返回

数据库乐观锁实现

数据库乐观锁方案一般只能适用于执行更新操作的过程,我们可以提前在对应的数据表中多添加一个字段,充当当前数据的版本标识。

这样每次对该数据库该表的这条数据执行更新时,都会将该版本标识作为一个条件,值为上次待更新数据中的版本标识的值。

具体流程步骤:

  • 客户端带着version字段请求服务端
  • 服务端执行update的时候需要给version+1,并且需要加version的更新条件如下SQL
 update t set stock = stock - 1 , version = version + 1 where id = #{id} and version = #{version}

数据库悲观锁实现

在这里插入图片描述
具体流程步骤:

  • 客户端通过业务id,访问服务端
  • 先查数据库是否存在该业务id,查库的时候需要加X锁
  • 如果存在则说明是重复请求,不存在则进行业务逻辑处理

JVM锁实现

JVM 锁实现是指通过 JVM 提供的内置锁如 Lock 或者是 synchronized 来实现幂等性。使用 JVM 锁来实现幂等性的一般流程为:首先通过 Lock 对代码段进行加锁操作,然后再判断此订单是否已经被处理过,如果未处理则开启事务执行订单处理,处理完成之后提交事务并释放锁,执行流程如下图所示:
在这里插入图片描述

JVM 锁存在的最大问题在于,它只能应用于单机环境,因为 Lock 本身为单机锁,所以它就不适应于分布式多机环境。

分布式锁实现

分布式锁实现解决JVM锁实现单机锁局限问题。
在这里插入图片描述

具体流程步骤:

  • 客户端先请求服务端,会拿到一个能代表这次请求业务的唯一字段
  • 将该字段以 SETNX 的方式存入 redis 中,并根据业务设置相应的超时时间
  • 如果设置成功,证明这是第一次请求,则执行后续的业务逻辑
  • 如果设置失败,则代表已经执行过当前请求,直接返回

Token实现

在这里插入图片描述
具体流程步骤:

  • 客户端会先发送一个请求去获取 token,服务端会生成一个全局唯一的 ID 作为 token 保存在 redis 中,同时把这个 ID 返回给客户端
  • 客户端第二次调用业务请求的时候必须携带这个 token
  • 服务端会校验这个 token,如果校验成功,则执行业务,并删除 redis 中的 token
  • 如果校验失败,说明 redis 中已经没有对应的 token,则表示重复操作,直接返回指定的结果给客户端

注意:
对 redis 中是否存在 token 以及删除的代码逻辑建议用 Lua 脚本实现,保证原子性
全局唯一 ID 可以用百度的 uid-generator、美团的 Leaf 去生成

总结

幂等性不但可以保证程序正常执行,还可以杜绝一些垃圾数据以及无效请求对系统资源的消耗。推荐使用分布式锁来实现,这样的解决方案更加通用。


http://chatgpt.dhexx.cn/article/RaQagg8Q.shtml

相关文章

开发中是如何保证接口幂等性的?

文章目录 一、定义二、业务场景三、保证幂等性常用方法方案1: insert前先select(基于mysql的分布式锁)方案2:加悲观锁 select * from table where id 1 for update(基于mysql的分布式锁)方案3:加乐观锁 增…

如何保证接口的幂等性?常见的实现方案有哪些?

什么是幂等性 幂等用于表示任意多次请求均与一次请求执行的结果相同,也就是说对于一个接口而言,无论调用了多少次,最终得到的结果都是一样的。 如何保证接口的幂等性 1、前端拦截 2、使用数据库实现幂等性 3、使用 JVM 锁实现幂等性 4、…

接口幂等性常见的解决方案

一、什么是接口幂等性? 接口幂等性就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。 举个最简单的例子,那就是支付,用户购买商品后支付,支付扣款成功,但是返回结果的…

接口幂等性解决方案

一、分布式锁解决方案 先说这种方案,在网上有一些文章说可以通过分布式锁来保证幂等性。但是我认为这种方案不能保证幂等性,不可取。看下面分析 ①、方案流程介绍 用户通过浏览器发起请求,服务端接收请求数据,并且从请求数据中…

什么是接口的幂等性,如何实现接口幂等性?一文搞定

微信搜索《Java鱼仔》,每天一个知识点不错过 每天一个知识点 什么是接口的幂等性,如何实现接口幂等性? (一)幂等性概念 幂等性原本是数学上的概念,用在接口上就可以理解为:同一个接口&#x…

什么是幂等性?四种接口幂等性方案详解

幂等性在我们的工作中无处不在,无论是支付场景还是下订单等核心场景都会涉及,也是分布式系统最常遇见的问题,除此之外,也是大厂面试的重灾区。 知道了幂等性的重要性,下面我就详细介绍幂等性以及具体的解决方案&#…

接口的幂等性

1、接口调用存在的问题 现如今我们的系统大多拆分为分布式 SOA,或者微服务,一套系统中包含了多个子系统服务,而一个子系统服务往往会去调用另一个服务,而服务调用服务无非就是使用 RPC 通信或者 restful。既然是通信,…

如何保证接口的幂等性?

什么是幂等性?所谓幂等,就是任意多次执行所产生的影响均与一次执行的影响相同。 为什么会产生接口幂等性问题 在计算机应用中,可能遇到网络抖动,临时故障,或者服务调用失败,尤其是分布式系统中,接口调用…

什么是接口的幂等性以及如何实现接口幂等性

目录 1、接口调用存在的问题 2、什么是接口的幂等性 3、不做接口的幂等性会产生什么影响 4、什么情况下需要保证接口的幂等性 4.1 select:查询操作 4.2 insert:新增操作 4.3 delete:删除操作 4.3.1 绝对删除 具有幂等性 4.3.2 相对删…

Python安装pygame教程

Python安装pygame教程 1、版本说明 由于python3.8与pygame存在不兼容的问题,因此在下载Python的时候,需要下载python3.8以下版本的,我下载的是python3.7.5 2、具体步骤 1、在本机控制台通过命令安装pygame pip install pygame 出现错误 …

Pygame 教程(2):重要的概念及对象

本章,将介绍 Pygame 中的重要概念及对象。 导航 上一章:创建第一个应用程序 下一章:绘制图形 文章目录 导航像素坐标Rect 对象Color 对象Surface 对象实例:矩形生成器创建初始窗口创建生成矩形的函数调用函数完整代码 结语 像素…

Pygame教程系列二:MoviePy视频播放篇

【前言】 在pygame 2.0.0版本之前,播放视频可以使用pygame.movie.Movie(xxxx.mpg)播放(只支持.mpg格式的视频),但是在pygame 2.0.0之后,作者因为觉得视频模块维护成本太高就给抛弃了,假如你使用pygame 2.0.0,还调用上述…

Pygame 教程(4):图像传输和绘制文本

本章,你将学会如何传输图像和绘制文本。 导航 上一章:绘制图形 下一章:监测游戏时间 文章目录 导航加载图像导出图像绘制文本实例:画板添加常量限制坐标定义属性绘制色板更改线条粗细处理鼠标事件处理键盘事件调用事件处理方法完…

Pygame基础教程(一)

写在前面的话: 本系列教程仅有一些在本机调试通过的代码(如代码中发现bug,恳请包涵)。除代码中出现的一些主要注释外,不会出现太多其他文字解释,但是,文章中会给出主要模块的官方文档地址。再次…

Pygame 教程(5):监测游戏时间

本章,你将学习如何监测游戏时间。 导航 上一章:图像传输和绘制文本 下一章:努力更新中…… 文章目录 导航监测时间游戏帧速率实例:绘图性能对比结语 监测时间 在游戏程序中,时常需要随着时间的流逝而做出不同的动作…

Pygame教程系列四:播放音频篇

【前言】 pygame播放音频文件这部分相对来说比较简单,主要是用到pygame.mixer模块,不过也有一些地方需要注意的,咱们直接先看看案例 1、案例效果图 2、案例代码 import pygame from mutagen.mp3 import MP3 # 标识是否退出循环 exitFlag Fa…

python3.8安装pygame_Python3.8安装Pygame教程

注:因为最近想用一下Python做一些简单小游戏的开发作为项目练手之用,而Pygame模块里面提供了大量的有用的方法和属性。今天我们就在之前安装过PyCharm的基础上,安装Pygame,下面是安装的步骤,希望能够帮到大家。 第一步…

Pygame 教程(3):绘制图形

本章,你将学习如何在 Pygame 中绘制图形。 导航 上一章:重要的概念及对象 下一章:图像传输和绘制文本 文章目录 导航抗锯齿draw 模块实例:跟随鼠标的图形创建初始窗口添加变量捕捉鼠标事件绘制图形完整代码 结语 抗锯齿 抗锯齿…

Mac Pycharm导入Pygame教程(超细)

首先先新建一个想要使用Pygame的项目 进入项目后,点击文件(File)——新项目设置(settings) 点击新项目的偏好设置(Preferences for new project ) 随后可以看到 点击Python 编译器&#xff0…

mac python3.8上怎么安装pygame 第三方库_Python3.8安装Pygame教程步骤详解

注:因为最近想用一下python做一些简单小游戏的开发作为项目练手之用,而Pygame模块里面提供了大量的有用的方法和属性。今天我们就在之前安装过PyCharm的基础上,安装Pygame,下面是安装的步骤,希望能够帮到大家。 第一步 安装Python和pip 如果已安装,使用python --version …