接口幂等性

2021/11/25 23:40:01

本文主要是介绍接口幂等性,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

1.什么是接口幂等性
幂等,英文叫Idempotence,幂等这个词源自于数学,幂等性是数学中的一个概念,常见于抽象代数中,表达的是N次变换与1次变换的结果相同;简单来说就是如果方法调用一次和多次产生的效果是相同的,那摩它就具有幂等性
幂等函数,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数,这些函数不会影响系统状态,也不用担心重复执行会对系统造成改变,幂等性本身是一个数学概念,在计算机的各个领域都有涉及和借用

HTTP维度
在HTTP/1.1规范中幂等性定义的是:
在这里插入图片描述
从定义上看,HTTP方法的幂等性是指一次和多次请求某一个资源应该具有同样的副作用

HTTP请求常见的有GET、DELETE、PUT、POST四种主要方法;

GET方法
HTTP GET方法用于获取资源,不应有副作用,所以是幂等的。

比如:GET https://www.wkcto.com/course/100不会改变资源的状态,不论调用一次还是N次都没有副作用

比如:GET http://www.wkcto.com/course/100不会改变资源的状态,不论调用一次还是N次都没有副作用

请注意,这里强调的是一次和N次具有相同的副作用,而不是每次GET的结果相同。

GET https://www.wkcto.com/course这个HTTP请求可能会每次得到不同的结果,但它本身是并没有任何副作用的,也就是指不多对数据库中的数据产生任何影响,只是单纯的从数据库获取数据,因而是满足幂等性的

DELETE方法

HTTP DELETE方法用于删除资源,有副作用,但是它应该满足幂等性。
比如:DELETE http://www/article/detail/10,调用一次和N次对系统产生的副作用是相同的,即删掉id为10的文章,因此调用者可以多次调用或刷新页面而不必担心引起错误

POST方法
HTTP POST所对应的URI为资源的接收者。
比如:
POST http://www.co/article的语义是在https://www.co/article下发表一篇文章,两次相同的post请求会在服务器端创建两份资源,所以POST不具有幂等性

PUT方法
HTTP PUT所对应的URI是要创建或更新资源。

比如:PUT http://www.wkcto.com/article/5231的语义是创建或更新ID为5231的文章,对同一URI进行多次PUT的副作用和一次PUT是相同的,都是把这条记录给改了,因此PUT方法具有幂等性

以上是主要针对RESTful风格的HTTP幂等性的讨论;
我们知道,http协议是一种面向资源的应用层协议,但对http协议的应用存在两种不同的方式:
一种是restful的,他把http当成应用层协议,遵守http协议的各种规定;
另一种是在HTTP协议之上封装了我们的RPC,没有完全把HTTP当成应用层协议,而是把HTTP协议作为了传输层协议,然后再HTTP之上建立自己的应用层协议,那摩抛开http协议的规范,幂等性是分布式系统的重要特性,所以不论是restful的web api设计还是RPC方式的其他api设计都应该考虑幂等性;

应用维度
幂等性衍生到软件工程中,它的语义是指:函数/接口可以使用相同的参数重复执行,不应该影响系统状态,也不会对系统造成改变。
也就是任意多次执行所产生的的影响均与一次执行所产生的的影响相同;
如果用户对于同一操作发起的一次请求或者多次请求所产生的的影响是一致的,不会因为多次调用(点击)而产生了副作用;
第一次请求的时候对资源产生了副作用,但是以后的多次请求都不会再对资源产生副作用,这里的副作用是指不会对结果产生破坏或者产生不可预估的结果。及幂等性=多次执行无副作用

2.产生幂等性场景

幂等性问题在我们的开发中,分布式、微服务架构中是随处可见的:
因网络波动,可能会引起重复的请求;
用户重复操作,用户在使用产品时可能会无意的触发多次下单交易,甚至没有响应而有意触发多次交易;
应用使用了失败或超时重试机制(如Nginx重试、RPC重试或业务层重试等)。

第三方平台的接口(如: 支付成功回调接口),因为异常导致多次异步回调;
中间件/应用服务根据自身的特性,也有可能进行重试
用户双击提交按钮;
页面重复刷新;
使用浏览器后退按钮重复之前的操作,导致重复提交表单;
使用浏览器历史记录重复提交表单;
浏览器重复的HTTP请求;
定时任务重复执行;

3.幂等性在哪一层实现
我们现在的项目架构一般都是分布式、微服务的架构,那摩在开发中在哪一层进行幂等设计呢?

经过一番分析,在数据访问层实现是比较合适的;

4.数据层的幂等性
数据访问层主要分为读请求写请求
读请求需要做幂等?很显然是不需要的;那摩写请求呢?涉及到需要做insert、update、delete数据库操作的,肯定是需要的;
那我们可以得出来一个结论,即不会改变数据的操作我们可以不做幂等,会改变数据的操作我们就一定要做幂等;

那我们逐个讨论写请求:insert、delete、update操作,首先我假设我没有做任何应用层面上的幂等操作。

insert:
对于insert操作,当我重复插入数据的时候会出现什么情况?这里分为两种情况:

  • 自增主键 (有幂等性问题)
  • 业务主键 (没有幂等性问题)

比如:insert into product_info(id,name,type,price,tm); 假如我的id是自增主键会有问题吗?显然一定会有幂等问题,因为会产生多条业务数据相同,但是主键不同的数据。
那如果是业务主键呢?即我假设对name、type、price建立唯一索引,这样就ok了,即使我id相同,数据库也会报错,但是这里是句玩笑话,你这样加索引的话可能第二天就会把你辞退,看着办吧。

delete
对于delete操作,当重复执行的时候会出现什么情况?这里也要分为两种情况:

  • 绝对值删除: delete from product_info where id = 1234; — 幂等的
  • 相对值删除: delete top(10) from product_info – 不是幂等(这里假设这条语句的意思是删除排名前10的数据)

如果是绝对值删除,重复操作两次是不会出现问题的,但是如果是相对值删除,重复操作就是重复删除多次

update
对于update操作,当重复更新数据的时候会出现什么情况?这里其实和删除操作是一样的,也需要分两种情况讨论:
相对值删除

绝对值删除

我们拿一个具体的例子分析:
update product_info set price = 99 where id = 1234; --(绝对值修改)幂等的
update product_info set price = price + 100 where id = 1234; – (相对值修改)不是幂等的

如果是绝对值修改,重复操作也不会有问题,但是相对值修改,一定会有问题,会重复修改多次,导致每一次price的值都会发生变化

select
最后是select操作,其实这个不用讨论,因为不会对数据发生的改变的操作我们不用做幂等

狭义与广义的幂等
以上的所有的讨论都是基于单库的,这是狭义上的幂等处理,但是在实际的业务场景中,比如分布式系统中,我们的一次请求可能有多个步骤,这种跨服务、跨事务请求的幂等处理怎么办呢?也就是广义上的幂等处理怎么办呢?其实这个就需要分布式事务来干这个事;

所以广义上的幂等处理通过分布式事务来解决,狭义上的幂等处理,对于服务分层来说只需要在数据访问层做幂等操作,而对于读写请求幂等处理,select其实我们不用处理,因为从规范层面上来讲,insert操作你只要要求必须有唯一的业务主键,delete操作在实际业务上是不会被允许的,select操作又不需要做幂等处理,那唯一需要处理的是update操作,但是也很简单,就把相对值转换为绝对值修改即可。 。。。未完…



这篇关于接口幂等性的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程