接口幂等性

简介: 接口幂等性一、定义

接口幂等性

一、定义

幂等(idempotent、idempotence)是一个数学与计算机学概念,常见于抽象代数中。


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


幂等函数,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数。这些函数不会影响系统状态,也不用担心重复执行会对系统造成改变。


例如,“setTrue()”函数就是一个幂等函数,无论多次执行,其结果都是一样的.更复杂的操作幂等保证是利用唯一交易号(流水号)实现。


这是来自百度百科的解释,讲人话幂等性就是指接口可重复调用,在调用方多次调用的情况下,接口最终得到的结果是一致的。


二、使用场景

对于查询的借口来说,可以天然的实现幂等性,因为不管查询多少次都是一样的结果。


而对于增删改的借口来说,我们也需要保证其接口的幂等性。


好比当用户多点击了几次创建商品的操作,这时候前端会重复请求一个新增的接口(要求后台执行一次创建),这时候后端重复创建了多条记录,这就是没有实现接口幂等性所带来的bug,也是我们需要避免的情况。


以下是接口幂等性可以使用的场景:


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

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

接口超时重复提交:很多时候 HTTP 客户端工具都默认开启超时重试的机制,尤其是第三方调用接口时候,为了防止网络波动超时等造成的请求失败,都会添加重试机制,导致一个请求提交多次。

消息进行重复消费:当使用 MQ 消息中间件时候,如果发生消息中间件出现错误未及时提交消费信息,导致发生重复消费。

三、影响

幂等性是为了简化客户端逻辑处理,能放置重复提交等操作,但却增加了服务端的逻辑复杂性和成本,其主要是:


把并行执行的功能改为串行执行,降低了执行效率。

增加了额外控制幂等的业务逻辑,复杂化了业务功能;

所以在使用时候需要考虑是否引入幂等性的必要性,根据实际业务场景具体分析,除了业务上的特殊要求外,一般情况下不需要引入的接口幂等性。


使用幂等性最大的优势在于使接口保证任何幂等性操作,免去因重试等造成系统产生的未知的问题


使用幂等性最大的优势在于使接口保证任何幂等性操作,免去因重试等造成系统产生的未知的问题

四、实现方式


该主键一般来说并不是使用数据库中的自增主键,而是使用分布式ID充当主键,这样才能保证分布式环境下ID的全局唯一性

防重Token令牌:集群环境采用token+redis(redis是单线程的,处理需要排队),单JVM环境采用token+jvm内存,针对客户端连续点击或调用方超时重试等情况


调用接口前向后端申请token,token放入redis(作为key,用户信息作为value)或jvm内存中,并设置有效时间

提交请求需携带token,后台验证是否存在token,以及value是否匹配,存在且匹配则请求成功并删除token,否则则请求失败

执行redis的查找和删除存在并发问题,在并发情况下,执行 Redis 查找数据与删除需要保证原子性,可以通过使用分布式锁或Lua表达式来注销查询和删除操作。

状态机制幂等:状态变更, 更新数据时判断状态


如果状态机已经处于下一个状态,这时候来了一个上一个状态的变更,理论上是不能够变更的

电商订单,订单支付状态 0 待支付,1 支付中,3 支付成功,4 支付失败

update order set status = 1 where status =0 and orderId = “201251487987”

该sql语句利用状态CAS 保证该操作的幂等

比如要进行订单支付,上来先用CAS更新订单状态

返回影响数为 1 代表修改成功,可以支付,继续执行支付业务代码

返回影响数为 0 代表修改失败,该订单已经不是待支付订单了

悲观锁:获取数据时加锁获取


在用户请求操作数据库前对表或行进行上锁,等完成操作后再将锁释放

此时若有第二次请求企图访问数据库则会在尝试获取锁时失败

乐观锁:只是在更新数据时锁表,其他时间不锁表,所以相对于悲观锁,效率更高


提前在对应的数据表中多添加一个字段,充当当前数据的版本标识

每次对该数据库该表的这条数据执行更新时,都会将该版本标识作为一个条件,值为上次待更新数据中的版本标识的值,保证一定更新的是某个版本对应下的信息

重复更新时,在第二次更新的时候版本已经改变,故无法更新成功以实现幂等

分布式锁:通过第三方的系统(redis或zookeeper),在业务系统插入数据或者更新数据,获取分布式锁,然后做操作,之后释放锁


插入数据的例子,如果是分布是系统,构建全局唯一索引比较困难,例如唯一性的字段没法确定,这时候可以引入分布式锁

某个长流程处理过程要求不能并发执行,可以在流程执行之前根据某个标志(用户ID+后缀等)获取分布式锁,其他流程执行时获取锁就会失败,也就是同一时间该流程只能有一个能执行成功,执行完成后,释放分布式锁(分布式锁要第三方系统提供)

缓存队列:将请求放入队列,后续使用异步任务处理队列中的数据,过滤掉重复的消息。 和防止重复消费道理是一样

相关文章
|
开发工具 git 开发者
深入解析:取消 Git Pull 操作的完整指南
【2月更文挑战第29天】
2069 0
|
消息中间件 存储 Kafka
Flink---11、状态管理(按键分区状态(值状态、列表状态、Map状态、归约状态、聚合状态)算子状态(列表状态、广播状态))
Flink---11、状态管理(按键分区状态(值状态、列表状态、Map状态、归约状态、聚合状态)算子状态(列表状态、广播状态))
|
6月前
|
缓存 人工智能 算法
不同业务怎么选服务器?CPU / 内存 / 带宽配置表
本文详解了服务器三大核心配置——CPU、内存、带宽,帮助读者快速理解服务器性能原理。结合不同业务场景,如个人博客、电商、数据库、直播等,提供配置选择建议,并强调合理搭配的重要性,避免资源浪费或瓶颈限制。内容实用,适合初学者和业务选型参考。
1020 0
|
缓存 监控 网络安全
使用CDN部署静态资源有哪些优势和注意事项
使用CDN部署静态资源能显著加速内容传递、减轻源服务器负载、提高可用性和容错性、节省带宽成本。但需选择合适的CDN提供商,合理配置缓存规则,确保安全性,监控性能,优化策略,避免缓存污染和处理资源版本问题,以实现最优效果。
560 4
|
机器学习/深度学习 人工智能 Ubuntu
|
监控 前端开发 JavaScript
前端稳定性工具-Sentry
【11月更文挑战第9天】Sentry 是一个开源的错误和性能监控平台,支持多种编程语言和框架。它能够捕获前端应用中的各种错误和性能问题,提供详细的错误信息和用户行为关联,帮助开发团队快速定位和解决问题,优化应用性能。但需注意隐私保护、数据准确性和成本控制。
2438 3
|
存储 并行计算 算法
CUDA统一内存:简化GPU编程的内存管理
在GPU编程中,内存管理是关键挑战之一。NVIDIA CUDA 6.0引入了统一内存,简化了CPU与GPU之间的数据传输。统一内存允许在单个地址空间内分配可被两者访问的内存,自动迁移数据,从而简化内存管理、提高性能并增强代码可扩展性。本文将详细介绍统一内存的工作原理、优势及其使用方法,帮助开发者更高效地开发CUDA应用程序。
|
开发者 索引 Python
【Python 基础】remove、del和pop有什么区别?
【5月更文挑战第8天】【Python 基础】remove、del和pop有什么区别?
|
人工智能 前端开发 JavaScript
探索前端技术栈:构建现代Web应用的基石
探索前端技术栈:构建现代Web应用的基石
676 1
|
JavaScript
如何在vue添加echarts图表
如何在vue添加echarts图表
511 0

热门文章

最新文章