什么是幂等运算?

#1 楼

在计算中,幂等运算是指如果使用相同的输入参数多次调用幂等运算,则不会产生任何其他影响。例如,从集合中删除某项可以被视为对该集合的幂等运算。

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

通过考虑数学定义中的x表示对象的状态,而f是可以使该对象发生变异的运算,可以调和这些稍微不同的定义。例如,考虑使用Python set及其discard方法。 discard方法从集合中删除一个元素,如果该元素不存在,则什么也不做。因此:

my_set.discard(x)


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

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


等幂运算通常在网络协议的设计中使用“通信协议”,在该协议中,保证执行一项操作的请求至少会发生一次,但也可能会发生多次。如果该操作是幂等的,则两次执行该操作没有任何危害。

有关更多信息,请参阅Wikipedia上关于幂等的文章。


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

评论


示例:由于上面的回答指出,幂等操作经常用于网络协议的设计中,因此,这是一个相关示例** GET并不假定更改服务器上的任何内容,因此GET是幂等的。在HTTP / Servlet上下文中,这意味着可以两次发出相同的请求,而不会产生负面影响。 ** POST不是幂等的。

– KNU
2014年4月1日上午10:37

“无状态”是“幂等”的同义词吗?

–迈克尔·奥索夫斯基
2014年12月5日17:09

@MichaelOsofsky:不,在答案的Python设置示例中,设置对象显然具有状态,并且还提供了一些幂等操作,例如丢弃。

– Greg Hewgill
2014年12月7日19:44

@MichaelOsofsky,也可以通过将状态包含在返回值中来以无状态的方式实现:discard([my_set,x])= [my_new_set,x]。因此,您可以丢弃(discard([my_set,x]))。请注意,[my_new_set,x]只是一个参数,其类型为2元组。

–起搏器
2015年3月10日在22:59



@Green在阳ot的情况下使用术语“相同效果”时,表示结果相同,而不是作用相同。第二次调用discard(x)将具有与第一次调用相同的效果:该集合将不再包含x。计算幂等性与系统的健壮性有关。由于事情可能会失败(例如,网络中断),因此当检测到故障时,如何恢复?最简单的恢复方法是再次执行此操作,但这仅在重新执行幂等的情况下才有效。例如。 throw(x)是幂等的,而pop()不是。都是关于错误恢复的。

–安德烈亚斯(Andreas)
16-4-27的15:27



#2 楼

幂等运算可以重复任意次,其结果将与仅进行一次相同。用算术在数字上加零是幂等的。

在“ RESTful” Web服务的上下文中讨论了幂等。 REST试图最大程度地利用HTTP来使程序访问Web内容,并且通常与基于SOAP的Web服务形成对比,后者只是在HTTP请求和响应中建立远程过程调用样式服务。

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

幂等在REST中扮演重要角色。如果您获取REST资源的表示形式(例如,从Flickr获取jpeg图像),并且操作失败,则可以一次又一次地重复GET,直到操作成功。对于Web服务,获取图像的次数无关紧要。同样,如果您使用RESTful Web服务来更新您的Twitter帐户信息,则可以多次输入新信息,以便从Web服务获得确认。将其放置一千次与放置一次相同。同样,将REST资源删除一千次与删除一次相同。幂等性因此使构建可抵抗通信错误的Web服务变得容易得多。

进一步阅读:RESTful Web Services,由Richardson和Ruby(幂等性在第103-104页讨论)和Roy Fielding的REST博士学位论文。 Fielding是HTTP 1.1 RFC-2616的作者之一,在第9.1.2节中讨论了幂等性。

评论


清晰明了。但这只是对幂等的一种解释。

–起搏器
2015年3月10日在21:45

“幂等”是一个很重的单词,因为它听起来很雄辩,并且具有足够的字符可以通过倍半方格检查。如果本杰明·皮尔斯(Benjamin Peirce)选择了一个听起来更简单的词,那么今天我们什至不会有这个问题。

–起搏器
15年3月11日在11:15

如何理解它:同样,将REST资源删除一千次与删除一次相同吗?如果资源已被删除,则无法再次删除。

–绿色
2015年10月10日在8:14

@Green,但是您不会第一次删除它。您发送一个删除请求。重要的是,您可以发送任意多个请求。

– Caleth
17年4月6日在12:54

我看到了@JimFerrans。我认为可能有一些与功能相关的原因(内置在HTTP本身中),为什么可以重新发送PUT而不必担心POST,而不必担心。现在看来,我们只需要遵循HTTP标准,并且其行为完全基于服务器的实现方式。

– mangusta
2月22日6:11



#3 楼

无论您调用该操作多少次,结果都将相同。

评论


我听说过幂等定义为以下任何一个或两个:1)对于给定的一组输入,它将始终返回相同的输出。 2)不产生任何副作用。我的问题是,如果一个函数符合#1,但不符合#2,因为它会导致与计算无关的副作用(例如,将请求记录到数据存储中),是否仍然认为它是幂等的?

–基思·贝内特(Keith Bennett)
2012年6月28日在22:32



调用操作的结果必须包括系统状态,因此,如果操作具有某种累积的副作用,则它不是幂等的;但是,如果无论调用多少次,副作用都使系统保持相同状态,则可能是幂等的。

–罗伯特
2012年7月17日在21:45

简短而可爱,我喜欢这种答案。不知道为什么我必须经常检查这个名词,这是一个不容忽视的名词。

–香料
2015年2月2日,12:59

@KeithBennett,第二个定义是错误的。 “无副作用”并不意味着幂等。等幂函数可能会产生副作用。例如。 MySQL的截断和删除。

–起搏器
2015年3月10日23:11

结果将是相同的(即系统状态),但是响应可能会有所不同(即REST服务上的HTTP状态代码)。

– G. Steigert
18年2月7日在11:13

#4 楼

幂等意味着一次执行一个操作或多次执行一个操作具有相同的效果。

示例:


乘以零。无论执行多少次,结果仍然为零。
设置布尔值标志。无论执行多少次,该标志都会保持设置状态。
从具有给定ID的数据库中删除一行。如果再次尝试,该行仍然消失。

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

对于具有副作用的函数,幂等性还意味着首次应用后不会引起其他副作用。如果愿意,您可以将世界状态视为该函数的附加“隐藏”参数。

请注意,在有并发操作正在进行的世界中,您可能会发现自己所进行的操作认为幂等不再如此(例如,在上面的示例中,另一个线程可以取消设置布尔值的值)。基本上,只要您具有并发性和可变状态,就需要对幂等性进行更仔细的考虑。

幂等性通常在构建健壮的系统中非常有用。例如,如果存在从第三方接收重复消息的风险,则使消息处理程序充当幂等操作将很有帮助,这样消息效果只会发生一次。

评论


如果对于纯函数f(x)= f(f(x)),是否表示f(x){return x + 1;}不是纯函数?因为f(x)!= f(f(x)):f(1)给出2而f(2)给出3。

–起搏器
15年3月10日在22:08

@Pacerier不,@ mikera说的是纯和幂等,表示f(x)= f(f(x))。但是正如@GregHewgill所提到的,为了使该定义有意义,您必须将x视为对象,并将f视为使对象状态发生变化的运算(即:f的输出是x的变化)。

–贾斯汀·J·史塔克(Justin J Stark)
16-10-17在16:14



#5 楼

只要传递相同的参数,即使多次调用,幂等运算也会在相同的状态下产生结果。

评论


听起来根本不合逻辑。 stackoverflow.com/questions/1077412/…

–绿色
15-10-10在8:36



我认为您可能会混淆幂等和确定性。

– Suncat2000
18年4月12日在17:33

#6 楼

只是想抛出一个证明幂等的真实用例。在JavaScript中,假设您正在定义一堆模型类(如在MVC模型中一样)。通常,这种实现方式在功能上等效于以下示例(基本示例):

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

  return Model;
}


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

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


但是,如果您尝试通过User从代码中的其他位置获取model('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');


评论


这个答案似乎不正确。幂等性是关于在给定输入参数的情况下调用您希望更改某些状态的操作,如果再次使用相同的参数进行调用,则对状态没有任何影响。但是在您的示例中,甚至在使用缓存之前,如果我们两次调用model('user'),这已经是幂等的,状态没有任何变化,只是创建了一个新的不同对象并将其返回给调用者(未存储)。您正在描述一种对象标识工厂模式,该模式可确保在调用之间返回“相同”对象,这很有用,但不能解释幂等性。

–灰
7月2日4:12



#7 楼

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

示例(Web应用程序上下文):

要点:
发出多个相同的请求与发出单个请求具有相同的效果。电子邮件消息系统中的一条消息已打开,并在数据库中标记为“已打开”。一个人可以多次打开该消息,但是这种重复的操作只会导致该消息处于“打开”状态。这是一个幂等操作。第一次使用与资源不匹配的信息(系统状态)对资源进行PUT更新时,系统状态将随着资源更新而改变。如果一个PUT重复对资源进行相同的更新,则更新中的信息将与每个PUT上已存在于系统中的信息相匹配,并且不会更改系统状态。具有相同信息的重复PUT是幂等的:第一个PUT可能会更改系统状态,而后续的PUT则不会。

非强制性:
如果某个操作总是导致状态改变,例如一遍又一遍地向用户发布同一条消息,则导致每条消息都会发送并存储在数据库中时间,我们说该操作是非必需的。

如果操作没有副作用,例如仅在网页上显示信息而数据库中没有任何更改(在换句话说,您仅在读取数据库),我们说该操作是NULLIPOTENT。所有GET均应无效。

在谈论系统状态时,我们显然忽略了希望的无害和不可避免的影响,例如日志记录和诊断。

#8 楼

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


等幂=可重新运行


例如,不能保证
Create操作本身如果执行多次,则运行时不会出错。
但是,如果有一个操作CreateOrUpdate,那么它将指出可重新运行性(幂等)。

评论


这是一个欺骗性的定义。可重运行性不能保证是幂等的。某个操作可以重新运行,并且在每次运行中都可以为结果添加其他效果,因此它不会是幂等的。

– Saeed Mohtasham
18年4月16日在14:38



#9 楼

任何第n个结果都将导致输出与第一个结果的值匹配的任何操作。例如,-1的绝对值为1。-1的绝对值的绝对值为1。-1的绝对值的绝对值的绝对值为1。依此类推。
另请参阅:什么时候使用递归真的很愚蠢?

评论


即使十年后,这也是一个精妙的答案。 +1

–snr
19年6月23日在5:41

#10 楼

幂等运算:如果多次执行,则没有副作用。
示例:从数据资源中检索值并进行打印的运算
非幂等运算:会造成一定危害的运算如果执行多次。 (当它们更改某些值或状态时)
示例:从银行帐户中提款的操作

评论


其实是错误的答案!对于幂等运算说“没有副作用”是不对的。对于非幂等运算来说,“造成一些伤害”是一个令人困惑的答案。

– Saeed Mohtasham
18年4月16日在15:37

#11 楼

一次或多次应用时,对集合的幂等运算将使其成员保持不变。

它可以是一元运算,如absolute(x),其中x属于一组正整数。在这里,absolute(absolute(x))= x。

它可以是二进制运算,就像集合与自己的并集总是会返回相同的集合。

干杯

评论


幂等运算是f(f(x))= f(x)的运算。 “保留其成员不变”不是正确的答案。

– Saeed Mohtasham
18年4月16日在15:44

#12 楼

理解幂等运算的一个很好的示例可能是使用远程钥匙锁定汽车。

lock是幂等运算。即使每次运行lock都有一些副作用(例如闪烁),无论您执行多少次锁定操作,汽车仍处于相同的锁定状态。

#13 楼

我的5c:
在集成和网络中,幂等性非常重要。
现实生活中的几个例子:
想象一下,我们将数据传递到目标系统。通过一系列消息传递的数据。
1。如果序列在通道中混合会发生什么? (因为网络软件包总是这样做:))。如果目标系统是幂等的,结果将不会有所不同。如果目标系统按顺序排列正确顺序,则必须在目标站点上实现重新排序器,这将恢复正确顺序。
2。如果消息重复,该怎么办?如果目标系统的通道未及时确认,则源系统(或通道本身)通常会发送该消息的另一个副本。结果,我们可以在目标系统端获得重复的消息。
如果目标系统是幂等的,它会照顾好它,结果不会有所不同。
如果目标系统不是幂等的,我们必须在通道的目标系统侧实现重复数据删除器。 br />

评论


与其他任何请求(或任何其他会改变系统状态的事件)隔离发送的单个请求的幂等性与重新排序请求不同。 HTTP PUT请求和HTTP DELETE请求都应分别幂等,但这并不意味着在同一URL上调用PUT和DELETE的顺序无关紧要,因为PUT请求可能会有副作用!

–罗宾·格林(Robin Green)
16-3-8在9:25



#14 楼

简而言之,幂等运算意味着无论您操作幂等运算多少次,该操作都不会导致不同的结果。

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

#15 楼

重试安全。

通常是了解其在计算机科学中含义的最简单方法。

评论


重试意味着第一次或上次失败。不太一样。

–拉瑟·V·卡尔森(Lasse V. Karlsen)
17年4月6日在12:37

谁编辑了我的问题并让我投了反对票?那不是我发布的文字??

– teknopaul
17-4-9在10:17



您可以通过单击答案下方的“ X个小时前编辑过”或类似内容的链接来检查编辑日志。

–拉瑟·V·卡尔森(Lasse V. Karlsen)
17年4月9日在19:17