什么是幂等操作?

什么是幂等操作?

在计算中,一个幂等运算是一个不具有附加效果的运算,如果它被相同的输入参数多次调用。 例如,从一个集合中删除一个项目可以被认为是该集合上的一个幂等操作。

在数学中,幂等运算是f(f(x))= f(x)的运算。 例如, abs()函数是幂等的,因为对于所有x abs(abs(x)) = abs(x)

这些略有不同的定义可以通过考虑数学定义中的x代表一个对象的状态来调和,而f是可以改变该对象的操作。 例如,考虑Python set及其discard方法。 discard方法从集合中删除一个元素,如果元素不存在,则不执行任何操作。 所以:

 my_set.discard(x) 

与两次执行相同的操作具有完全相同的效果:

 my_set.discard(x) my_set.discard(x) 

在网络协议的设计中经常使用幂等操作,其中执行操作的请求至少保证一次,但也可能发生一次以上。 如果手术是幂等的,那么两次或两次以上的手术都没有危害。

有关更多信息,请参阅维基百科关于幂等性的文章。


上面的答案以前有一些不正确和误导性的例子。 以下在2014年4月之前写的评论是指较旧的版本。

一个幂等操作可以重复任意次数,结果将与只做一次相同。 在算术中,给数字加零是幂等的。

在“RESTful”Web服务的背景下,“幂等性”被讨论了很多。 REST旨在最大限度地利用HTTP来为程序提供对Web内容的访问,通常与基于SOAP的Web服务相比,这些服务只是在HTTP请求和响应内部建立远程过程调用风格的服务。

REST将Web应用程序组织成“资源”(如Twitter用户或Flickr图像),然后使用POST,PUT,GET和DELETE的HTTP动词来创建,更新,读取和删除这些资源。

幂等性在REST中起着重要的作用。 如果获取REST资源的表示(例如,从Flickr获取JPEG图像),并且操作失败,则可以重复GET操作直到操作成功。 对于Web服务来说,获取图像的次数并不重要。 同样,如果您使用REST风格的Web服务来更新您的Twitter帐户信息,您可以多次PUT新信息,以便从Web服务获得确认。 放一千次与PUT-it一次是一样的。 同样,删除REST资源一千次与删除一次相同。 因此,同构性使构建一个对通信错误具有弹性的Web服务变得容易得多。

进一步阅读:Richardson和Ruby提出的RESTful Web服务 (幂泛函在第103-104页讨论)和Roy Fielding 关于REST的博士论文 。 Fielding是HTTP 1.1,RFC-2616的作者之一,在第9.1.2节中讨论了幂等性。

无论你多少次操作,结果都是一样的。

幂等性意味着一次应用操作或多次应用操作具有相同的效果。

例子:

  • 乘以零。 不管你做了多少次,结果都是零。
  • 设置一个布尔标志。 不管你做了多少次,旗子都保持着。
  • 使用给定的ID从数据库中删除一行。 如果你再试一次,这一行仍然没有了。

对于纯函数 (没有副作用的函数),则幂等性意味着f(x)= f(f(x))= f(f(f(x)))= f(f(f(f(x))) )= ……所有的x值

对于具有副作用的功能来说,幂等性还意味着在第一次应用之后不会引起额外的副作用。 如果你愿意的话,你可以把世界的状态看作是一个额外的“隐藏”参数。

请注意,在并发动作正在进行的世界中,您可能会发现您认为是幂等的操作不再是这样(例如,另一个线程可能会取消上例中布尔标志的值)。 基本上每当你有并发和可变的状态时,你需要更仔细地考虑幂等性。

幂等性在构建健壮的系统中通常是有用的属性。 例如,如果存在可能从第三方接收到重复消息的风险,则将消息处理程序用作幂等操作是有帮助的,以便消息效果只发生一次。

如果您调用一次或多次,幂等操作会将所有内容都保持在相同的状态,只要您传入相同的参数即可。

只是想抛出一个真实的用例来证明幂等性。 在JavaScript中,假设您正在定义一堆模型类(如在MVC模型中)。 通常实现的方式在功能上与此类似(基本示例):

 function model(name) { function Model() { this.name = name; } return Model; } 

然后你可以定义像这样的新类:

 var User = model('user'); var Article = model('article'); 

但是,如果你想通过model('user')从代码中的其他地方获取User类,它将会失败:

 var User = model('user'); // ... then somewhere else in the code (in a different scope) var User = model('user'); 

这两个User构造函数将会不同。 那是,

 model('user') !== model('user'); 

为了使其具有幂等性 ,您只需添加某种缓存机制,如下所示:

 var collection = {}; function model(name) { if (collection[name]) return collection[name]; function Model() { this.name = name; } collection[name] = Model; return Model; } 

通过添加缓存,每次你做model('user')它将是同一个对象,所以它是幂等的。 所以:

 model('user') === model('user'); 

幂等操作:多次执行时没有副作用的操作。
示例 :从数据资源中检索值并进行打印的操作

非幂等操作:多次执行会导致一些伤害的操作。 (当他们改变一些价值观或状态时)
示例:从银行账户中退出的操作

一套幂等操作在应用一次或多次时保持其成员不变。

它可以是像绝对(x)这样的一元操作,其中x属于一组正整数。 这里绝对(绝对(x))= x。

它可以是一个二元操作,像一个集合与它自己总是会返回相同的集合。

干杯

相当详细和技术性的答案。 只需添加一个简单的定义。

Idempotent =可重新运行

例如,如果多次执行,则本身的Create操作不保证无误地运行。 但是,如果有一个操作CreateOrUpdate那么它表示重新运行(幂等性)。

任何第n个结果都会导致输出与第一个结果的值相匹配。 例如-1的绝对值是1. -1的绝对值的绝对值是1. -1的绝对值的绝对值的绝对值是1.等等。

另请参见:什么时候使用递归会非常愚蠢?

幂等操作是可以多次应用的操作,操作或请求,而不会改变结果,即系统的状态,超出最初的应用程序。

示例(WEB APP背景):

NULLIPOTENT:如果一个操作没有任何副作用,比如纯粹在网页上显示信息而不改变数据库(换句话说,你只是读数据库),我们说操作是NULLIPOTENT。 所有的GET应该是无效的。 否则,使用POST。

IDEMPOTENT:电子邮件消息系统中的消息在数据库中打开并标记为“已打开”。 可以多次打开该消息,但是这种重复的行为只会导致该消息处于“打开”状态。 这是一个幂等的操作。

NON-IDEMPOTENT:如果一个操作总是导致状态改变,比如反复向用户发送同样的消息,导致每次发送一个新的消息并存储在数据库中,那么我们说这个操作是NON-IDEMPOTENT。

当谈到系统的状态时,我们显然忽略了无害的,不可避免的影响,如日志和诊断。

幂等方法

无论多少次被调用,幂等方法都会产生相同的结果。

  • GET方法是幂等的,因为多次调用GET资源将始终返回相同的响应。

  • PUT方法是幂等的,因为多次调用PUT方法会更新相同的资源,而不会改变结果。

  • POST不是幂等的,多次调用POST方法可能会有不同的结果,并会导致创建新的资源。

  • DELETE是幂等的,因为一旦资源被删除,它就消失了,多次调用这个方法不会改变结果。

简而言之 ,幂等操作意味着无论您操作幂等操作多少次,操作都不会产生不同的结果。

例如,根据HTTP规范的定义, GET, HEAD, PUT, and DELETE是幂等操作; 但POST and PATCH不是。 这就是为什么有时POST被PATCH替换。

我的5c:在集成和网络方面,幂等性非常重要。 现实生活中的几个例子:想象一下,我们将数据传递给目标系统。 数据由一系列消息传递。 1.如果序列在频道中混合会发生什么? (因为网络包总是:))。 如果目标系统是幂等的,结果将不会有所不同。 如果目标系统依赖于顺序中的正确顺序,我们必须在目标站点上执行重排器,这将恢复正确的顺序。 2.如果信息重复,会发生什么? 如果目标系统的信道没有及时得到确认,源系统(或信道本身)通常会发送另一个消息副本。 因此,我们可以在目标系统端重复消息。 如果目标系统是幂等的,它就会照顾它,结果将不会有所不同。 如果目标系统不是幂等的,我们必须在通道的目标系统端实施重复数据删除器。

从RESTful服务的角度来看,对于一个操作(或服务调用)来说是幂等的,客户可以重复地做同样的调用,同时产生相同的结果。 换句话说,制作多个相同的请求与制作单个请求具有相同的效果。 请注意,尽管幂等操作在服务器上产生相同的结果(无副作用),但响应本身可能不一样(例如资源的状态可能在请求之间改变)。

GET表示一个幂等只读操作。 您可以重复向服务器发送GET请求,而不会产生不良影响,因为GET不会(或不应该)更改服务器上的状态。

另一方面,POST则是用于提交信用卡交易,向购物车添加相册或更改密码的请求类型。 POST请求通常会修改服务器上的状态,并重复请求可能会产生不良影响(如双重计费)。 许多浏览器帮助用户避免重复POST请求。

Web应用程序通常使用GET请求来读取和POST请求进行写入(通常包括更新,创建和删除)。 支付音乐的请求使用POST。 搜索音乐的请求,您看下面的场景,使用GET。

我读了其他的答案,似乎对幂等性有一些困惑。 我认为这是因为有时它看起来像它在编程中的用法不同于它的数学定义(例如,将它用于REST动词)。

如果它让你感到困惑,那么看看这篇文章,它使事情变得更简单https://mortoray.com/2014/09/05/what-is-an-idempotent-function/ 。 它解释了我们总是可以从编程中重写幂等性的情况来遵循其数学定义。

重试安全。

通常是理解计算机科学意义的最简单的方法。