保证接口幂等性

2023-09-21 14:21:39

什么是幂等性

幂等性是系统服务对外一种承诺,承诺只要调用接口成功,外部多次调用对系统的影响是一致的。声明为幂等的服务会认为外部调用失败是常态,并且失败之后必然会有重试。

什么情况下需要幂等

以SQL为例:

SELECT col1 FROM tab1 WHER col2=2,无论执行多少次都不会改变状态,是天然的幂等。
UPDATE tab1 SET col1=1 WHERE col2=2,无论执行成功多少次状态都是一致的,因此也是幂等操作。
UPDATE tab1 SET col1=col1+1 WHERE col2=2,每次执行的结果都会发生变化,这种不是幂等的。
insert into user(userid,name) values(1,'a') 如userid为唯一主键,即重复操作上面的业务,只会插入一条用户数据,具备幂等性。
如userid不是主键,可以重复,那上面业务多次操作,数据都会新增多条,不具备幂等性。
delete from user where userid=1,多次操作,结果一样,具备幂等性

如何保证幂等

token机制

1、服务端提供了发送token的接口。我们在分析业务的时候,哪些业务是存在幂等问题的,就必须在执行业务前,先去获取token,服务器会把token保存到redis中。

2、然后调用业务接口请求时,把token携带过去,一般放在请求头部。

3、服务器判断token是否存在redis中,存在表示第一次请求,然后删除token,继续执行业务。

4、如果判断token不存在redis中,就表示是重复操作,直接返回重复标记给client,这样就保证了业务代码,不被重复执行。

关键点 先删除token,还是后删除token。

后删除token:如果进行业务处理成功后,删除redis中的token失败了,这样就导致了有可能会发生重复请求,因为token没有被删除。这个问题其实是数据库和缓存redis数据不一致问题,后续会写文章进行讲解。

先删除token:如果系统出现问题导致业务处理出现异常,业务处理没有成功,接口调用方也没有获取到明确的结果,然后进行重试,但token已经删除掉了,服务端判断token不存在,认为是重复请求,就直接返回了,无法进行业务处理了。

先删除token可以保证不会因为重复请求,业务数据出现问题。出现业务异常,可以让调用方配合处理一下,重新获取新的token,再次由业务调用方发起重试请求就ok了。
token机制缺点
业务请求每次请求,都会有额外的请求(一次获取token请求、判断token是否存在的业务)。其实真实的生产环境中,1万请求也许只会存在10个左右的请求会发生重试,为了这10个请求,我们让9990个请求都发生了额外的请求。

乐观锁机制

这种方法适合在更新的场景中,update t_goods set count = count -1 , version = version + 1 where good_id=2 and version = 1
根据version版本,也就是在操作库存前先获取当前商品的version版本号,然后操作的时候带上此version号。我们梳理下,我们第一次操作库存时,得到version为1,调用库存服务version变成了2;但返回给订单服务出现了问题,订单服务又一次发起调用库存服务,当订单服务传如的version还是1,再执行上面的sql语句时,就不会执行;因为version已经变为2了,where条件就不成立。这样就保证了不管调用几次,只会真正的处理一次。
乐观锁主要使用于处理读多写少的问题

唯一主键
这个机制是利用了数据库的主键唯一约束的特性,解决了在insert场景时幂等问题。但主键的要求不是自增的主键,这样就需要业务生成全局唯一的主键。

如果是分库分表场景下,路由规则要保证相同请求下,落地在同一个数据库和同一表中,要不然数据库主键约束就不起效果了,因为是不同的数据库和表主键不相关。

防重表
使用订单号orderNo做为去重表的唯一索引,把唯一索引插入去重表,再进行业务操作,且他们在同一个事务中。这个保证了重复请求时,因为去重表有唯一约束,导致请求失败,避免了幂等问题。这里要注意的是,去重表和业务表应该在同一库中,这样就保证了在同一个事务,即使业务操作失败了,也会把去重表的数据回滚。这个很好的保证了数据一致性。

唯一ID
调用接口时,生成一个唯一id,redis将数据保存到集合中(去重),存在即处理过。

更多推荐

FFmpeg入门及编译

文章目录前言一、FFmpeg简介二、基本组成1、封装模块-AVFormat2、编解码模块-AVCodec3、滤镜模块-AVFilter4、视频图像转换计算模块-swscale5、音频转换计算模块-swresample6、AVUtil-核心工具库7、AVDevice-硬件采集,加速,显示三、命令行工具四、FFmpeg环境

jvm深入研究文档--java中的堆--详解!--jvm底层探索(1)

阿丹:JVM的内存分区包括以下几个部分:堆区(Heap)-这是JVM的主要部分,用于存储实例对象和大多数Java对象,如数组和用户定义的类。方法区(MethodArea)-这是线程私有的,用于存放类对象(加载好的类)。栈区(Stack)-这是线程私有的,包括虚拟机栈和本地方法栈。虚拟机栈用于保存调用关系的内存空间,而本

Linux学习之Redis使用

搭建Redis服务器在主机redis64运行redis服务#安装redis服务[root@redis64~]#yuminstall-yredis#启动redis服务并开机启动[root@redis64~]#systemctlenableredis--now#查看redis端口[root@redis64~]#ss-tnl

redis 常用数据结构2

目录listLPUSHLRANGELPUSHXRPUSHRPUSHXLPOPRPOPLINDEXLINSERTLLENLREMLTRIMLSETBLPOP/BRPOP编码方式setSADDSMEMBERSSISMEMBERSPOPSCARDSRANDMEMBERSMOVESREMSINTERSINTERSTORESUN

基于javaweb的顶岗实习管理系统(jsp+servlet)

系统简介本项目采用eclipse工具开发,jsp+servlet+jquery技术编写,数据库采用的是mysql,navicat开发工具。三个角色:管理员,教师,学生模块简介管理员:1、登录2、学生管理3、公告管理4、教师管理5、任务分类管理6、实习任务管理7、实习任务申请管理8、实习报告分数管理学生:1、登录2、个人

MYSQL存储引擎基础知识介绍

下面重点介绍几种常用的存储引擎,并对比各个存储引擎之间的区别,以帮助读者理解不同存储引擎的使用方式。MyISAMMyISAM是MySQL的默认存储引擎。MyISAM不支持事务、也不支持外键,其优势是访问的速度快,对事务完整性没有要求或者以SELECT、INSERT为主的应用基本上都可以使用这个引擎来创建表。每个MyIS

JMeter-BeanShell预处理程序和BeanShell后置处理程序的应用

一、什么是BeanShell?BeanShell是用Java写成的,一个小型的、免费的、可以下载的、嵌入式的Java源代码解释器,JMeter性能测试工具也充分接纳了BeanShell解释器,封装成了可配置的BeanShell前置和后置处理器,分别是BeanShellPreprocessor(BeanShell预处理程

MySQL表的增删改查(基础)

一、新增(Create)--创建一张学生表DROPTABLEIFEXISTSstudent;CREATETABLEstudent(idINT,snINTcomment'学号',nameVARCHAR(20)comment'姓名',qq_mailVARCHAR(20)comment'QQ邮箱');1.单行数据+全列插入-

Windows网络服务综测刷题

作者简介:一名云计算网络运维人员、每天分享网络与运维的技术与干货。座右铭:低头赶路,敬事如仪个人主页:网络豆的主页​​​​​前言本章将会讲解Windows网络服务的刷题一.刷题在WindowsServer2016系统中,通过添加Web服务器(IIS)角色并进行正确配置,可以提供()应用服务。(选择两项)AB使用wind

Java版企业电子招标采购系统源码Spring Cloud + Spring Boot +二次开发+ MybatisPlus + Redis

项目说明随着公司的快速发展,企业人员和经营规模不断壮大,公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境,最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范,以及审计监督要求;通过电子化平台提高招投标工作的公开性和透明性;通过电子化招投标,使得招标采购的质量更高、速度

效率工具3-计算机网络工具

查看各个状态的tcp连接情况netstat-n|awk‘/^tcp/{++S[$NF]}END{for(ainS)printa,S[a]}’/^tcp/正则表达式匹配netstat命令输出的匹配部分,即以"TCP"开始的行{++S[$NF]}对于符合条件的每一行,awk命令将使用数组S来计算每种连接状态的连接数$NF代

热文推荐