关于语言不可知:什么是幂等操作?

What is an idempotent operation?

什么是等幂运算?


在计算中,如果使用相同的输入参数多次调用等幂运算,则等幂运算没有额外的效果。例如,从集合中移除项可以被视为集合上的等幂运算。

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

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

1
my_set.discard(x)

与两次相同的操作效果完全相同:

1
2
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资源的表示(例如,从Flickr获取一个jpeg图像),并且操作失败,您可以一次又一次地重复get,直到操作成功。对于Web服务来说,获取多少次图像并不重要。同样,如果您使用一个RESTful Web服务来更新您的Twitter帐户信息,您可以尽可能多次地放置新信息,以便从Web服务获得确认。把它放一千次和把它放一次是一样的。同样,将一个REST资源删除一千次与删除一次相同。因此,等幂性使得构建一个能够抵御通信错误的Web服务变得容易得多。

进一步阅读:由Richardson和Ruby撰写的RESTful Web服务(第103-104页讨论了等幂性),以及RoyFielding关于REST的博士论文。菲尔丁是HTTP1.1,RFC-2616的作者之一,该书在第9.1.2节中讨论了等幂性。


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


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

实例:

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

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

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

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

在建立鲁棒系统中,等幂性通常是一个有用的性质。例如,如果存在可能从第三方收到重复消息的风险,那么让消息处理程序充当等幂运算有助于使消息效果只发生一次。


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


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

1
2
3
4
5
6
7
function model(name) {
  function Model() {
    this.name = name;
  }

  return Model;
}

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

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

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

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

这两个User构造器是不同的。也就是说,

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
var collection = {};

function model(name) {
  if (collection[name])
    return collection[name];

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

  collection[name] = Model;
  return Model;
}

通过添加缓存,每次执行model('user')时,它都是同一个对象,因此是等幂的。所以:

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


等幂运算是一种操作、操作或请求,可以多次应用,而不改变初始应用之外的结果,即系统状态。

示例(Web应用上下文):

NULLIPOTENT:如果一个操作没有任何副作用,比如仅仅在网页上显示信息而数据库没有任何变化(换句话说,您只是在读取数据库),那么我们认为该操作是无效的。一切都是无效的。否则,使用post。

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

非等幂的:如果一个操作总是导致状态的改变,比如一遍又一遍地向用户发送相同的消息,每次都会导致一条新消息被发送并存储在数据库中,那么我们就说这个操作是非等幂的。

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


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

Idempotent = Re-runnable

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


等幂运算:如果多次执行就没有副作用的运算。< BR>示例:从数据资源中检索值并说打印该值的操作
BR/>非等幂运算:如果多次执行会造成一定伤害的运算。(当它们改变某些值或状态时)< BR>示例:从银行帐户中提取的操作


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

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

它可以是一个二进制运算,就像集合本身的集合总是返回相同的集合一样。

干杯


每个第n个结果都将导致与第一个结果的值匹配的输出的任何操作。例如-1的绝对值是1。绝对值-1的绝对值是1。绝对值-1的绝对值的绝对值为1。等等。

另请参见:什么时候使用递归才是真正愚蠢的?


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

例如,根据HTTP规范的定义,GET, HEAD, PUT, and DELETE是等幂运算,而POST and PATCH不是等幂运算。这就是为什么有时候post会被补丁取代。


我的5C:在集成和网络中,等幂性非常重要。现实生活中的几个例子:想象一下,我们向目标系统交付数据。由一系列消息传递的数据。1。如果序列在通道中混合会发生什么?(网络包总是这样做:)如果目标系统是幂等的,则结果不会是不同的。如果目标系统依赖于序列中的正确顺序,则必须在目标站点上实现ReSeCeNeReR,这将恢复正确的顺序。2。如果有消息副本会发生什么?如果目标系统的信道不及时应答,则源系统(或信道本身)通常发送消息的另一副本。因此,我们可以在目标系统侧有重复的消息。如果目标系统是幂等的,它会处理它,结果不会是不同的。如果目标系统不是幂等的,我们必须在信道的目标系统侧实现去重复制器。


重试安全。

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