什么是幂等运算?


Answers:


964

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

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

通过考虑数学定义中的x表示对象的状态,并且f是可以使该对象变异的运算,可以调和这些稍有不同的定义。例如,考虑Pythonset及其discard方法。该discard方法从集合中删除一个元素,如果该元素不存在,则不执行任何操作。所以:

my_set.discard(x)

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

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

幂等操作通常用于网络协议的设计中,在该协议中,执行一项操作的请求至少会发生一次,但也可能会发生多次。如果该操作是幂等的,则两次执行此操作不会有任何危害。

有关更多信息,请参见有关幂等性的Wikipedia文章。


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


6
例子:因为上面的回答指出这Idempotent operations are often used in the design of network protocols是一个相关的例子,** GET不能改变服务器上的任何东西,所以GET是幂等的。在HTTP / Servlet上下文中,这意味着可以两次发出相同的请求,而不会产生负面影响。** POST不是幂等的。
KNU

1
“无状态”是“幂等”的同义词吗?
Michael Osofsky 2014年

2
@MichaelOsofsky:不,在set答案的Python 示例中,set对象显然具有状态,并且还提供了一些幂等操作,例如discard
Greg Hewgill 2014年

1
@MichaelOsofsky,discard也可以通过将状态包含在返回值中来以无状态方式实现:discard([my_set, x]) = [my_new_set, x]。这样就可以了discard(discard([my_set, x]))。请注意,[my_new_set, x]只有一个参数,它的类型是2元组。
Pacerier

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

138

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

在“ 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服务变得容易得多。

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


清晰明了。然而,这不过只是一个幂等的解释。
Pacerier

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

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

1
@Green,但是您不会第一次删除它。您发送删除请求。重要的是您可以发送任意数量的请求。
卡雷斯(Caleth)'17

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

109

无论您调用该操作多少次,结果都是一样的。


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

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

4
简短而可爱,我喜欢这种答案。不知道为什么我必须经常检查这个术语,这是一个不陪我的日子。
Prancer

1
@KeithBennett,第二个定义是错误的。“无副作用”并不意味着幂等。幂等函数会产生副作用。例如MySQL truncatedelete
Pacerier,2015年

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

50

幂等是指一次执行一项操作或多次执行一项操作具有相同的效果。

例子:

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

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

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

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

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


1
如果是纯函数f(x) = f(f(x)),那f(x){return x+1;}是不是纯函数?因为f(x) != f(f(x))f(1)给2同时f(2)给出了3
Pacerier

1
@Pacerier不,@ mikera说的是纯净幂等的含义f(x) = f(f(x))。但是正如@GregHewgill所提到的,为了使此定义有意义,您必须考虑x将其视为对象以及f使对象状态发生变化的操作(即:的输出f是mutated x)。
贾斯汀·J·史塔克


16

只是想抛出一个证明幂等的真实用例。在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');

10

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

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

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

非强制性:如果某个操作总是引起状态变化,例如一次又一次地向用户发布同一条消息,导致每次都发送新消息并将其存储在数据库中,那么我们就说该操作是非强制性的。

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

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


9

幂等运算:如果多次执行,则没有副作用。
示例:一种从数据资源中检索值并进行打印的

操作非等幂操作:如果多次执行该操作会造成一定危害。(当它们更改某些值或状态时)
示例:从银行帐户中提取的操作


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

9

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

幂等=可重新运行

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


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

7

一个集合上的幂等运算在被应用一次或多次后,其成员保持不变。

它可以是绝对值(x)之类的一元运算,其中x属于一组正整数。这里的absolute(absolute(x))= x。

它可以是二进制运算,就像集合与自身的将始终返回同一集合一样。

干杯


幂等运算是f(f(x))= f(x)的运算。“让成员保持不变”不是正确的答案。
Saeed Mohtasham

7

任何第n个结果都将导致输出与第一个结果的值匹配的任何操作。例如,-1的绝对值为1。-1的绝对值的绝对值为1。-1的绝对值的绝对值的绝对值为1。依此类推。

另请参阅:什么时候使用递归真的很愚蠢?


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

2

理解幂等操作的一个很好的例子可能是用遥控钥匙锁定汽车。

log(Car.state) // unlocked

Remote.lock();
log(Car.state) // locked

Remote.lock();
Remote.lock();
Remote.lock();
log(Car.state) // locked

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


1

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


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

1

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

例如,根据HTTP规范的定义,GET, HEAD, PUT, and DELETE是幂等运算;但是POST and PATCH不是。因此,有时会POST被替换PUT


-4

重试安全。

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


1
重试意味着第一次或上次失败。不太一样。
Lasse V. Karlsen

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

您可以通过单击答案下方的“ X个小时前编辑过”或类似内容的链接来检查编辑日志。
Lasse V. Karlsen
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.