什么是幂等操作?
在计算中,幂等操作是指如果使用相同的输入参数多次调用它,则不会产生额外的影响.例如,从集合中删除项目可以被视为对集合的幂等操作.
在数学中,幂等操作是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月之前撰写的评论参考旧版本.
幂等操作可以重复任意次数,结果将与仅执行一次相同.在算术中,向数字加零是幂等的.
在"RESTful"Web服务的上下文中对Idempotence进行了大量讨论.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服务获得确认.投入一千次与投入一次相同.类似地,删除REST资源一千次与删除一次相同.因此,幂等性使得构建对通信错误具有弹性的Web服务变得容易得多.
进一步阅读:Ricfuldson和Ruby的RESTful Web服务(第103-104页讨论了幂等性),以及Roy Fielding 关于REST的博士论文.Fielding是HTTP 1.1,RFC-2616的作者之一,它在第9.1.2节中讨论了幂等性.
无论您调用多少次操作,结果都是一样的.
幂等意味着应用一次操作或多次应用操作具有相同的效果.
例子:
乘以零.无论你做了多少次,结果仍然是零.
设置布尔标志.无论你做多少次,旗帜都会保持不变.
使用给定ID从数据库中删除行.如果你再试一次,那行仍然没有了.
对于纯函数(没有副作用的函数),幂等性意味着f(x)= f(f(x))= f(f(f(x)))= f(f(f(f(x))) )= ......对于x的所有值
对于具有副作用的功能,幂等性还意味着在第一次应用后不会引起额外的副作用.如果您愿意,可以将世界状态视为该函数的附加"隐藏"参数.
请注意,在您正在进行并发操作的世界中,您可能会发现您认为幂等的操作不再是这样(例如,另一个线程可能会取消上面示例中的布尔标志的值).基本上每当你有并发性和可变状态时,你需要更加仔细地考虑幂等性.
幂等性通常是构建稳健系统的有用属性.例如,如果存在从第三方收到重复消息的风险,则将消息处理程序用作幂等操作是有帮助的,这样消息效果只会发生一次.
即使您多次调用它,幂等操作也会以相同的状态生成结果,前提是您传入相同的参数.
只是想抛弃一个展示幂等性的真实用例.在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');
幂等操作是可以多次应用的操作,动作或请求,而不会改变结果,即系统状态,超出初始应用程序.
示例(WEB应用程序上下文):
NULLIPOTENT:如果一个操作没有副作用,比如纯粹在网页上显示信息而数据库没有任何变化(换句话说你只是在读数据库),我们说操作是NULLIPOTENT.所有GET都应该是无效的.否则,请使用POST.
IDEMPOTENT:电子邮件消息系统中的消息已打开,并在数据库中标记为"已打开".可以多次打开该消息,但这种重复操作只会导致该消息处于"打开"状态.这是一种幂等操作.
NON-IDEMPOTENT:如果一个操作总是导致状态改变,比如一遍又一遍地向用户发送相同的消息,导致每次都发送并存储在数据库中的新消息,我们说该操作是NON-IDEMPOTENT.
在谈论系统的状态时,我们显然忽略了希望无害和不可避免的影响,如记录和诊断.
幂等操作:如果多次执行则没有副作用的操作.
示例:从数据资源中检索值的操作,并将其打印出
非幂等操作:如果多次执行会导致某些损害的操作.(因为它们会更改某些值或状态)
示例:退出银行帐户的操作
相当详细和技术性的答案.只需添加一个简单的定义.
幂等=重新运行
例如,
Create
如果多次执行,则无法确保操作本身无错误地运行.但是,如果有一个操作,CreateOrUpdate
那么它表示重新运行(Idempotency).
每个第n个结果都会导致输出与第1个结果的值相匹配.例如,-1的绝对值是1.绝对值-1的绝对值是1.绝对值绝对值-1的绝对值是1.依此类推.
另请参阅:何时使用递归会非常愚蠢?
当应用一次或多次时,对集合的幂等操作使其成员保持不变.
它可以是像absolute(x)这样的一元运算,其中x属于一组正整数.这里绝对(绝对(x))= x.
它可以是二元运算,如集合与其自身的并集将始终返回相同的集合.
干杯