什么是幂等运算?


当前回答

幂等运算可以重复任意次数,结果与只做一次是一样的。在算术中,一个数加零是幂等的。

幂等性在“RESTful”web服务的上下文中被讨论了很多。REST寻求最大限度地利用HTTP来为程序提供对web内容的访问,并且通常与基于soap的web服务进行设置,后者只是在HTTP请求和响应中隐藏远程过程调用样式的服务。

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

Idempotence plays an important role in REST. If you GET a representation of a REST resource (eg, GET a jpeg image from Flickr), and the operation fails, you can just repeat the GET again and again until the operation succeeds. To the web service, it doesn't matter how many times the image is gotten. Likewise, if you use a RESTful web service to update your Twitter account information, you can PUT the new information as many times as it takes in order to get confirmation from the web service. PUT-ing it a thousand times is the same as PUT-ing it once. Similarly DELETE-ing a REST resource a thousand times is the same as deleting it once. Idempotence thus makes it a lot easier to construct a web service that's resilient to communication errors.

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

其他回答

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

例子:

乘以0。无论你做多少次,结果仍然是零。 设置布尔标志。不管你做了多少次,旗帜都不会动摇。 从数据库中删除具有给定ID的行。如果你再试一次,排还是消失了。

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

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

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

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

对于工作流管理器(如Apache workflow),如果管道中的幂等操作失败,系统可以自动重试该任务而不影响系统。即使日志发生了变化,这也很好,因为您可以看到事件。

在这种情况下,最重要的是您的系统可以重试失败的任务,并且不会弄乱管道(例如,每次重试都在表中添加相同的数据)

只是想提出一个真实的用例来证明幂等性。在JavaScript中,假设你定义了一堆模型类(就像MVC模型一样)。它的实现方式通常是这样的(基本示例):

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

  return Model;
}

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

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

但如果你试图通过模型(' 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;
}

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

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

幂等运算即使调用多次也会产生相同状态的结果,前提是传入相同的参数。

幂等操作:多次执行没有副作用的操作。 示例:从数据资源检索值并打印值的操作 非幂等操作:多次执行会造成伤害的操作。(当它们改变某些值或状态时) 示例:从银行账户提款的操作