接口幂等方案

news2024/11/24 14:35:25

文章目录

  • 概要
  • 方案
      • 乐观锁
      • 数据库唯一索引
      • 令牌token
          • token通过另一个接口从服务端获取
          • 客户端自身生成token
  • 总结

概要

所谓接口幂等性,就是一次和多次请求某一个资源对于资源本身应该具有同样的影响。接口幂等的应用很广,小到防止表单重复提交,大到分布式系统高可用下的重试策略引起的多次请求。

对接口的请求无外乎增删改查,首先查肯定无需考虑,在没有增删操作的前提下查询肯定是幂等的。其次对于删除也无需考虑,删一次和删多次效果一样。那么需要考虑的就是增加和修改了。

方案

乐观锁

了解乐观锁的同学知道它本质就是版本控制,所以该方案只适合修改(更新)这种场景

对于修改,有一个前提就是资源已经存在了,那么用户想修改该资源就表示用户已经查询到资源了。
大概原理就是用户查询得到资源版本号version,在请求修改接口的时候将其携带上,用于修改操作的控制。
以MySQL为例如下:

update user set name=‘bob’,version=2+1 where id=1 and version=2

这样后续version=2的请求就不会生效。
步骤:

  1. 客户端通过查询接口获取资源版本号;
  2. 客户端请求修改接口,并携带资源版本号;
  3. 服务端收到请求,按照版本号更新数据;
  4. 更新数据条数大于零则成功,否则更新失败,此时返回失败提示或默认成功都可以视业务需求而定。

优点:

  • 简单,只需加一个version字段就可以实现

缺点:

  • 有很大的局限性,只适合修改这种场景,并且要明确每个版本只允许修改一次是正常业务,不然A,B用户都持有version=2,A修改后,B修改不生效是bug还是不是呢?要厘清边界

PS:这里只是以MySQL为例,MySQL只是一个资源载体,你也可以把它放到Redis(原子性用lua脚本保证即可)。

数据库唯一索引

利用唯一索引的唯一性来实现接口幂等,该方案只适合增加(插入)这种场景

场景:插入的数据中含有唯一字段。举一个不太恰当的例子,一个订单只允许对应一条费用记录,这个时候订单id就可以作为费用记录插入时的唯一字段。

步骤:

  1. 客户端提交数据,携带唯一字段(这个唯一字段哪里来呢?)
  2. 服务端收到请求,执行数据插入;
  3. 数据库插入成功则成功,否则需判断是否是唯一索引冲突。

优点:

  • 简单,只需要建立合适的唯一索引即可

缺点:

  • 有很大的局限性,只适合插入场景,并且是简单的插入场景

令牌token

上面两种方案都是在资源本身上进行操作,跳出资源本身,想象空间就很大了。令牌token就是脱离资源本身来实现接口幂等的方案,见下图:
在这里插入图片描述
这里聊一下上一节提到的唯一字段(token)哪里来呢?

  1. 通过另一个接口从服务端获取,经典场景就是防止表单重复提交;
  2. 客户端自身生成,经典场景如微服务架构下订单生成后再通过库存模块接口扣商品库存数量,此时订单模块就是客户端,其本身的订单号即可作为token来实现幂等。

根据token来源延伸出一下两种方案。
ps:token是唯一的

token通过另一个接口从服务端获取

幂等接口1
时序图如上图,逻辑很清晰,没啥可说的,不过这里要唠叨一下:

检测token存在与删除token这两个操作要保证原子性,否则多个请求并发过来,都查到token存在,再都删除,都执行业务逻辑,那接口就丧失了幂等性。

基于上述原因,考虑到常用的存储中间件,那token存储方式最好选用Redis,而不是MySQL,MongoDB之类的。Redis可以用lua脚本保证查询与删除命令的原子执行,而MySQL,MongoDB之类的就不好搞了,单点应用加锁也不是不行,多点呢?上分布式锁?那直接用Redis不香吗?

客户端自身生成token

幂等接口2
流程图如上,逻辑很清晰,没啥可说的,不过这里也要唠叨一下:

存储token可以选Redis,也可以是MySQL,MongoDB之类的:

  • 选Redis检测token存在用set NX即可;
  • 选MySQL,MongoDB之类的,则在token字段上建立唯一索引,借用唯一索引特性来检测,此时捕获唯一索引冲突错误即可。

ps:这里可以思考下,token存储是否要删除呢?多久之后删除比较好,可以根据自身业务看是否需要,需要的话用Redis set NX EX非常方便。

总结

本文讲述了几种实现接口幂等的方案,可以根据自身业务做出最好的选择,一般来说没有任何一种幂等方案可以适用于所有场景,但一令牌token的两种模式足以应付常见的场景了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/599728.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用kettle完成学生成绩登记需求

(一) 使用kettle完成学生成绩登记需求 学生成绩表下表所示。(自己创建一个学生表) 在MySQL中创建一个名为school的数据库,并在school数据库中创建一个名为score的表,使用Kettle将Excel形式的学生成绩表导入MySQL的score表 1&am…

机器视觉海康工业相机SDK参数设置获取

视觉人机器视觉培训-缺陷检测项目-食品行业草鸡蛋外观检测 相机参数类型可分为六类,除 command 参数外,每一类都有其对应的设置与获取函数接口。 表 1 参数类型及对应函数接口介绍 *详细函数接口可参考 SDK 手册: ​C:\Program Files (x86)\MVS\Development\Documentation…

【已解决】微信小程序报错:request 合法域名校验出错 如若已在管理后台更新域名配置,请刷新项目配置后重新编译项目,操作路径:“详情-域名信息”

【已解决】微信小程序报错:request 合法域名校验出错 如若已在管理后台更新域名配置,请刷新项目配置后重新编译项目,操作路径:“详情-域名信息” 场景复现解决方法 知识专栏专栏链接微信小程序专栏https://blog.csdn.net/xsl_hr/c…

工控设备如何防勒索病毒

目前现状 无论是中小企业还是大型企事业单位,均有属于自己的内网或公有云服务器。这些服务器有的是专门的SVN、GIT代码服务器,有的是文档存储服务器,有的是应用服务器。服务器是企业的核心命脉,所有知识产权及多年心血都集中汇总…

LeetCode——Pow(x, n)

一、题目 50. Pow(x, n) - 力扣(Leetcode) 实现 pow(x, n) ,即计算 x 的整数 n 次幂函数(即,xⁿ )。 示例 1: 输入:x 2.00000, n 10 输出:1024.00000示例 2&#x…

Jetpack Compose中的状态栏适配(Window Insets)

除了app的内容区域外,还有一些其他的固定元素会显示在手机屏幕上,顶部的状态栏、 刘海、 底部的导航栏,还有输入法键盘,它们都是系统的UI, 也叫Insets. 如图所示: 顶部的状态栏通常被用来展示通知, 设备状态等; 底部导…

软考A计划-网络规划设计师-学习笔记-上

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资源分享&am…

Linux 如何判断文件的类型

在Linux中&#xff0c;我们如何判断一个文件的类型和用户权限呢&#xff1f; 在c语言中&#xff0c;Linux为我们提供了一个结构体stat我们可以通过 #include<sys/stat.h>引入后使用。然后通过stat中的st_mode来判断文件的类型。如下图&#xff0c;我们要知道文件是什么类…

超级入门:R 语言的 5 种基本数据类型

一、R语言简介 R语言是一种用于统计计算和绘图的编程语言&#xff0c;它是由新西兰奥克兰大学的 Ross Ihaka 和 Robert Gentleman 开发的。R语言支持向量和矩阵计算&#xff0c;因此也可以用于数值分析和线性代数。它主要应用于数据分析、统计学习、数据挖掘、数据可视化等领域…

【Springboot】集成QQ邮箱信息发送

系列文章目录 文章目录 系列文章目录前言添加Maven依赖QQ邮箱开启POP服务配置application.properties文件Controller层编写 vue前端&#xff08;也可以直接省略&#xff09; 前言 这篇博客用于简单实现SpringBoot中发送请求&#xff0c;用户可以收到邮件。 添加Maven依赖 <…

ISIS 实验

(1)拓扑图 2&#xff09;需求&#xff1a; -实现PC1和PC2的通信 3&#xff09;配置步骤&#xff1a; -配置接口IP地址 -开启ISIS---类似于在OSPF中创建进程 -配置NET地址---类似于在OSPF中创建区域&#xff0c;指定Router-id -在接口上启用ISIS--类似于在OSPFv2中用ne…

SKNet讲解

SKNet讲解 0. 引言1. 网络结构1.1 Split部分1.2 Fuse部分1.3 Select部分1.4 三分支的情况 2. SKNet网络体系结构3. 分析与解释4. 代码总结 0. 引言 视皮层神经元的感受野大小受刺激的调节&#xff0c;即对不同刺激&#xff0c;卷积核的大小应该不同&#xff0c;但在构建CNN时一…

<DB2>《DB2创建分区表及相关操作》(精华)

《DB2创建分区表及相关操作》 1 基本概念2 操作2.1 查看数据库中存在的分区表2.2 查看分区表详细2.3 断开对数据表的访问连接2.4 备份数据2.5 拆离分区2.6 添加分区2.7 导入数据2.8 校验前后数据2.9 删除临时表数据 1 基本概念 当表中的数据量不断增大&#xff0c;查询数据的速…

使用Kettle实现数据排序

一、Kettle的安装 1.下载Kettle的安装包文件 在Windows系统中打开浏览器&#xff0c;访问Kettle官网&#xff08;https://sourceforge.net/projects/pentaho/&#xff09;&#xff0c;下载Kettle安装文件pdi-ce-9.1.0.0-324.zip。 或者在我的百度网盘分享里面下载 链接&…

【软件测试】软件测试总结笔记(2)

软件测试过程&#xff08;内容&#xff09; 1.单元测试基本概念定义⭐单元测试环境⭐单元测试内容单元测试用例的设计思路⭐单元测试的过程 2. 集成测试集成测试内容集成测试优点⭐集成测试层次集成测试方法Drivers and Stubs ⭐集成策略&#xff08;基于分解的集成&#xff09…

crontab定时任务介绍

1 crontab概述 crontab是linux操作系统上用来设置定时任务的基础命令&#xff0c;是基于crond服务实现任务调度执行。 当安装完成操作系统后&#xff0c;默认会安装crond服务及其附属命令&#xff0c;并且会自动启动crond进程&#xff0c;crond进程每分钟会定期检查是否有要执…

Python量化交易:策略创建运行流程

学习目标 目标 知道策略的创建和运行知道策略的相关设置知道RQ的策略运行流程应用 无 1、体验创建策略、运行策略流程 1.1 创建策略 1.2 策略界面 2、 策略界面功能、运行介绍 2.1 一个完整的策略需要做的事情 选择策略的运行信息&#xff1a; 选择运行区间和初始资金选择回…

水库大坝安全问题有哪些?

我国现有水库大坝9.8万余座&#xff0c;80%水库大坝修建于上世纪50至70年代&#xff0c;受经济、技术等历史因素的影响&#xff0c;存在坝体结构破损、坝基渗漏、坝体渗漏、坝面变形等严重的安全隐患。 一、水库大坝的安全问题主要包括以下几个方面&#xff1a; 1.坝体结构破损…

“微商城”项目(3页面布局)

1.设置标题 设置页面头部标题&#xff0c;方便告诉用户当前显示的是哪一个页面。编辑src\router.js文件&#xff0c;示例代码如下。 routes: [{ path: /, redirect: /home, meta: { title: 首页 } },{ path: /home, component: Home, name: home, meta: { title: 首页 } } ] …

ConditionObject的await方法分析

ConditionObject的await方法分析 判断当前线程是否中断&#xff0c;中断直接抛出非法监视器状态异常要是没有中断则通过addConditionWaiter()方法将该节点加入到Condition的单向链表中通过fullyRelease(node)方法一次新释放掉锁资源初始化一个状态模式为0的标记执行while判断&…