写点什么

REST 之中的幂等指的是什么?

  • 2013-05-11
  • 本文字数:1688 字

    阅读完需:约 6 分钟

REST (或者至少是 HTTP)的一个重要方面就是一些操作(动作)是幂等的。正如 Gregor Roth 在多年前所说的那样:

PUT 方法是幂等的。幂等的方法意味着请求成功执行所得到的的结果不依赖于该方法被执行的次数。

幂等也是在 SOA 设计模式中所讨论的一个问题。多年以来,围绕着 REST 以及相对于其他方式它所能带来的收益已经有了很多的讨论,在这个过程中,幂等只是一个方面,通常我们认为已经对其有所理解了,实际上并没有进行充分地研究。但是,最近在面向服务架构(Service Oriented Architecture)邮件列表中有一个帖子,针对这个看起来很直观的理念,激发了很多的讨论。初始的帖子是这样的:

目前我正在审视我们服务的幂等性并提出一个应用于企业的规定性指导,这个指导将会用于创建幂等服务的场景之中。问题在于,所有的服务都需要是幂等的吗?这现实吗?

它引用了另外的一篇 blog ,在这篇文章中,作者这样说:

当然,对于服务的提供者来说,实现幂等会比较复杂。而复杂性就会花费金钱。这可能就是幂等的服务如此稀少的原因。[…] 但是,服务只要成为幂等的,那么它就会非常简单,并且能够保证跨集成边界的数据一致性。服务 _ 应该 _ 是幂等的。这应该是架构和服务设计的原则。尤其是对于那些被很多消费者使用的服务更应如此。你不能将保持数据一致的复杂性推给你的消费者,对吧?消费者就是你的客户,你应该这样善待他们。如果你能为他们带来便利的话,你会有更多的消费者。

初始的这个帖子引起了很多的响应,包括来自 Cap Gemini 的 Steve Jones ,他这样说到:

幂等是 IT 行业中巨大的垃圾词汇之一,它的意思是“内存中的幂等”(idempotent in memory)。如果你有一个评论的服务,它具备更新的功能,从服务调用者的视角来看,服务必须要维护和管理状态。那你的含义就是它能够在内存中横向扩展。如果你更新状态的话,包括在数据库中,那么就不能保证是幂等的。幂等指的是当你使用相同的值调用相同的功能时,结果完全一致,这是它的数学定义。如果你改变过状态,那么就不是幂等的,而“数据库更新”并不会改变任何事情。

Mark Baker 曾经在 REST 这个话题上曾经有过很多回复,回应了 Steve:

就像你的评论样例所述,确实存在非幂等的状态更新,将一些数据更新为特定的值也会是幂等的更新…因为很显然如果用相同的输入执行多次的话,结果会是相同的。

Steve 在这一点上与 Mark 的观点是一致的:如果具有相同输入的一个操作没有改变任何的事情,那么它是幂等的。但是,如果这个操作改变了任意的状态,比如说它记录了这个请求的最后时间,那么它就不是幂等的。

在 IT 行业中,这个术语长久以来被人们滥用了,这一点我“感触颇深”,我曾经多次见过这样的场景,人们宣称一些事情是“幂等的”只是因为它在内存中是无状态的,尽管其消费者要达到的效果是记录性的事务。

Mark 同意 Steve 的严格定义,但是他相信这不能应用于初始请求的上下文之中,也就是:分布式系统中的幂等性:

[…] 这个词汇只对于接口有意义而不是实现。所以,如果我定义一个操作,比如说“set”,并将其定义为幂等的,那么它会只关系到客户端,即便在这个接口的实现中会产生日志。

另外一个参与者 Ashaf Galal,断言所有“读的服务”(reading services)都是幂等的,因为这样的服务只会返回数据。但是,Steve 指出,这是一个过于简单的视角,有时候一个操作呈现出来的是幂等的,它的实现可以做任何事情但它需要是幂等的就可以(这再次提出了这个问题,那就是这种区分是否重要):

[…] 读的功能不一定是幂等的。“getNextIterator()”是一个读的功能,它不是幂等的,因为它会渐进迭代器。银行账号请求余额可能也不是幂等的,因为会创建审计日志。两个连续调用返回的结果可能是相同的(如果没有变化发生的话),但是日志条目是不同的。

Ashaf 回应了 Steve,他说幂等是服务的属性而不是接口的属性。

客户端需要从服务那里得到适当的响应,他并不关心服务是不是幂等的,是不是要记录日志。

那么,其他人怎么想的呢?对于幂等的含义,是否还有误解?如果一个被视为幂等的操作实际上会改变一些状态,如 Steve 所提到的更新日志,那么这有关系吗?

英文原文链接: What Is Idempotent in REST?

2013-05-11 07:4526501

评论

发布
暂无评论
发现更多内容

我认为“写作平台”还缺少读者

小天同学

产品 反馈 写作平台 建议

附录3、Docker-compose 命令使用指南

悟尘

Docker Docker-compose

附录4、Docker-compose 配置文件编写指南

悟尘

Docker Docker-compose

源码分析 Vector 和 ArrayList

张sir

Java 源码 collection

Node.js 必知必会(安装配置、应用实例及同步控制)

悟尘

node.js

Netty 源码解析(三): Netty 的 Future 和 Promise

猿灯塔

web集群架构

桥哥技术之路

二、基于 Dockerfile 构建并运行镜像

悟尘

Docker Kubernetes 容器 k8s Compose

为什么说此前的WiFi安全方案都是小弟?

石君

wifi 无线网络 无线网络安全 Wi-Fi安全

游戏夜读 | 设计师的数据模型

game1night

告诉你一个学习编程的诀窍(建议收藏)

ithuangqing

学习 编程 自学编程

八、Kubernetes 入门实践

悟尘

Docker Kubernetes 容器 k8s Compose

写在开头

杨友峰

Java 期现

Hexo-deployer-cos-cdn 插件安装使用指南

悟尘

Hexo COS CDN Hexo-deployer-cos-cdn

VSCode-aliyun-oss-paste-image 插件安装使用指南

悟尘

vscode Paste-image

长假将至,推荐两个好东西

池建强

算法 视觉笔记

四、Docker 网络原理、分类及容器互联配置

悟尘

Docker Kubernetes 容器 k8s Compose

六、基于多阶段构建减小镜像体积降低复杂度

悟尘

Docker Kubernetes 容器 k8s Compose

附录2、Dockerfile 参考及最佳实践

悟尘

Docker Dockerfile

意想不到的收获哦

南辞

附录1、Docker 常用命令及示例

悟尘

Docker 容器

Hexo-admonition 插件安装使用指南

悟尘

Hexo Hexo-admonition Admonition

废掉一个人最好的办法是让他忙到没有时间思考

熊斌

程序员 职场 思考

五、Docker 数据持久化存储与性能调优

悟尘

Docker 容器 k8s Compose kubernet

七、Docker Compose 入门实践

悟尘

Docker Kubernetes 容器 k8s Compose

使用Typora + PicGo 图床 + jsDelivr CDN实现高效 Markdown 创作

悟尘

Typora PicGo iPic jsDelivr CDN

Redis高可用-哨兵模式配置

Geek_0o5u34

redis 高可用 主从配置 redis高可用 redis哨兵模式

三、基于 Docker-registry/Nexus3 搭建本地仓库

悟尘

Docker Kubernetes 容器 k8s Compose

Netty 源码解析(二):Netty 的 Channel

猿灯塔

Netty

一、Docker基础入门及架构介绍

悟尘

Docker Kubernetes 容器 k8s Compose

H5功能足够强大,为什么还要微信小程序?

顾强

微信小程序 移动应用

REST之中的幂等指的是什么?_SOA_Mark Little_InfoQ精选文章