1053

什么是幂等操作?

4

15 回答 15

1194

在计算中,幂等操作是指使用相同的输入参数多次调用它时不会产生额外影响的操作。例如,从集合中删除一个项目可以被认为是对集合的幂等操作。

在数学中,幂等运算是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 月之前撰写的评论指的是较旧的修订版。

于 2009-07-03T01:10:53.897 回答
165

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

幂等性在“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 帐户信息,您可以尽可能多地 PUT 新信息,以便从 Web 服务获得确认。PUT 一千次与 PUT 一次相同。同样,删除 REST 资源一千次与删除一次相同。因此,幂等性使得构建对通信错误具有弹性的 Web 服务变得更加容易。

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

于 2009-07-03T01:47:45.507 回答
128

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

于 2009-07-03T01:10:23.803 回答
57

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

例子:

  • 乘以零。不管你做了多少次,结果仍然是零。
  • 设置一个布尔标志。无论你做了多少次,标志都会保持不变。
  • 从具有给定 ID 的数据库中删除一行。如果您再试一次,该行仍然消失。

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

对于有副作用的函数,幂等性还意味着第一次应用后不会产生额外的副作用。如果您愿意,您可以将世界状态视为函数的附加“隐藏”参数。

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

幂等性通常是构建健壮系统的有用属性。例如,如果您可能会收到来自第三方的重复消息的风险,那么让消息处理程序充当幂等操作是有帮助的,这样消息效果只会发生一次。

于 2012-03-05T04:49:12.167 回答
31

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

log(Car.state) // unlocked

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

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

lock是幂等运算。即使每次运行都有一些副作用lock,比如眨眼,无论你运行多少次锁操作,汽车仍然处于相同的锁定状态。

于 2019-09-18T09:03:36.043 回答
28

即使您多次调用幂等操作,只要您传入相同的参数,它也会以相同的状态产生结果。

于 2009-07-03T01:13:54.017 回答
17

只是想抛出一个演示幂等性的真实用例。在 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');
于 2013-10-09T01:30:44.257 回答
17

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

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

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

NON-IDEMPOTENT:如果一个操作总是导致状态的变化,比如一遍又一遍地向用户发布相同的消息,导致每次发送一条新消息并存储在数据库中,我们就说该操作是 NON-IDEMPOTENT 的。

NULLIPOTENT:如果一个操作没有副作用,比如纯粹在网页上显示信息而不对数据库进行任何更改(换句话说,您只是在读取数据库),我们就说该操作是 NULLIPOTENT。所有 GET 都应该是无效的。

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

于 2015-08-03T22:46:59.373 回答
11

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

幂等 = 可重新运行

例如, Create如果多次执行,操作本身不能保证运行无误。但是如果有一个操作CreateOrUpdate,那么它就说明了可重运行性(幂等性)。

于 2015-08-13T10:59:41.213 回答
10

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

的操作 非幂等操作:如果多次执行会造成一定危害的操作。(因为它们改变了一些值或状态)
示例:从银行账户取款的操作

于 2012-12-06T14:42:39.860 回答
9

这是任何操作,每第 n 个结果将导致输出与第一个结果的值匹配。比如-1的绝对值是1。-1的绝对值的绝对值是1。-1的绝对值的绝对值的绝对值是1。以此类推。

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

于 2009-07-03T01:15:25.993 回答
8

对集合的幂等操作在应用一次或多次时使其成员保持不变。

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

它可以是二元运算,例如集合与自身的联合总是返回相同的集合。

干杯

于 2009-07-03T01:26:46.657 回答
3

简而言之,幂等操作是指无论你操作多少次幂等操作,操作都不会导致不同的结果。

例如,根据HTTP规范的定义,GET, HEAD, PUT, and DELETE是幂等操作;然而POST and PATCH不是。这就是为什么有时会POSTPUT.

于 2016-03-25T08:50:07.733 回答
1

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

于 2013-11-07T16:11:59.923 回答
0

如果多次执行一个操作相当于执行一次,则称该操作是幂等的。

例如:将音量设置为20。无论电视的音量设置为20多少次,最终的结果都是音量为20。即使一个进程执行该操作 50/100 次或更多,在进程结束时,音量将是 20。

反例:将音量加 1。如果一个进程执行此操作 50 次,则最终音量将为初始 Volume + 50,如果一个进程执行该操作 100 次,则最终音量将为初始 Volume + 100。正如您可以清楚地看到,最终结果会根据操作执行的次数而有所不同。因此,我们可以得出结论,该操作不是幂等的。

我用粗体突出了最终结果。


如果您从编程的角度考虑,假设我有一个操作,其中一个函数f作为foo输入,输出f设置为fooback。如果在进程结束时(执行此操作 50/100 次或更多次),我的foo变量保存它在仅执行一次操作时所做的值,则该操作是幂等的,否则不是。

foo = <some random value here, let's say -2>

{ foo = f( foo ) }   大括号概述了操作

如果f返回输入的平方,则该操作不是幂等的。因为foo最后会(-2) raised to the power (number of times operation is executed)

如果f返回输入的绝对值,则该操作是幂等的,因为无论执行多少次操作都foo将是abs(-2).
在这里,最终结果被定义为变量的最终值foo


在数学意义上,幂等性的含义略有不同:
f(f(....f(x))) = f(x)
这里的输出f(x)作为输入再次传递,f而编程并不总是如此。

于 2022-01-12T11:44:53.650 回答