每个工程师都应该了解的:聊聊幂等

转载至:http://mp.weixin.qq.com/s/EDkuMW5-hdIxs2GXMFnj_Q

什么是幂等(Idempotency)?简单来说,一个操作如果具有任意多次执行所产生的影响均与一次执行的影响相同,我们就称之为幂等。

这样说来,似乎很容易理解。但要知道,这样的定义,其实是一个语义范畴对行为结果的定义。如何用语法和规则去确保行为能达到这个结果,往往需要很谨慎的设计和实现。实际系统中,幂等是一个极为重要的概念。无论是在大型互联网应用还是企业级架构中,我们都见到 REST API 被越来越多的采用。而正确实现幂等,往往是 API 中最难的技术点之一。

先说为什么重要。举一个简单易懂的例子。

比如你要处理一次电商网站收款或者付款的交易。当你给微信支付发送这个付款请求后,一个顺利的场景,是没有任何错误发生,微信支付收到你的付款请求,处理所有转账,然后返回一个 HTTP 200 消息表示交易完成。

那如果发出请求后,有个请求超时,你再也没有收到关于这个请求是成功还是失败的的回执,又该如何呢?

这里就有很多种可能情况:

  • 这个请求在到达微信支付端前就已经发生超时,微信支付从来没有收到这样的请求。
  • 这个请求到达微信支付端,但是支付交易失败,这时发生超时,微信支付收到这样的请求,但没有处理成功。
  • 这个请求到达微信支付端,并且支付交易成功,这时发生超时,微信支付收到这样的请求,处理成功,但是没有回执。
  • 这个请求到达微信支付端,并且支付交易成功,并且发回回执,然而因为网络原因回执丢失,客户端超时,微信支付收到这样的请求,处理成功,发出回执,但是客户没有收到。

很直观的一个想法,也是现实中用户最常见的做法,是重新提交一次支付请求。但是这样就有一个潜在的问题:请求超时是上面的哪一种情况?会不会引发多次支付的可能性?

这就涉及到系统中的幂等是如何实现的了。

那么幂等又该如何实现呢?“多次执行所产生的影响均与一次执行的影响相同”,简而言之,我们需要一个 Dedup(去重)的机制。这往往有很多不同的实现方法,但是有两个很关键的因素:

一是 Idempotency Key(幂等令牌)。也就是客户端和服务器端通过什么来识别这实际上是同一个请求,或是同一个请求的多次 retry(尝试)。这往往需要双方又一个既定的协议。往往是类似账单号或者交易 token(令牌)这样一个可以唯一标识同一个请求意愿的元素。通常由客户端生成。

二是 Uniqueness Guarantee(确保唯一性)。服务器端用什么机制去确保同一个请求一定不会被处理两次,也就是微信支付怎么确保同一笔交易不会因为客户端发送两次请求就被处理多次。最通常的做法是利用数据库。比如把幂等令牌所在的数据库表的 Column(列)作为 unique indexed。这样,当你试图存储两个含有同样令牌的请求时,必定有一个会报错。注意,简单的读检查并不一定行,因为读与读之间会有 Race Condition(竞争条件),因此还是有可能出错。

如果一个系统可以正确的处理和实现上面的两个要素,那么基本就能达到幂等的需求。那么现实系统中常见的问题都出在哪里呢?

  1. 一是幂等令牌什么时候产生,怎么产生?这一点很重要。拿上面的例子来说。就算微信支付可以保证每一个请求对应的支付交易一定只会被处理一次。但是这个请求的多次重复,一定要共有某一个微信可以识别的标识。假如客户端对同一笔交易的多次请求,产生的幂等令牌并不相同,那不论你别的地方多么完美,都没有可能保证 “一个操作如果具有任意多次执行所产生的影响均与一次执行的影响相同”。
  2. 二是有没有令牌被误删的可能。这是上面的问题的一个特殊情况。幂等令牌是由客户端生成的。那么如果生成的令牌在被使用后(一次微信支付请求中使用了),不小心因为 DB rollback 等原因被删除了。那么客户端就不知道自己其实已经发过一次请求。就有可能生成一个新的账单,并产生全新的令牌,而服务端将对此一无所知。
  3. 三是各种竞争条件。上面说的用 DB 读来确保唯一性经常因为竞争而不工作。其实一个需要幂等的系统中,保证唯一性的各个环节和实现,都要考虑 Race Condition。
  4. 四是对请求 Retry 的处理。这大部分是服务器端要做的。一个常见的方法是区分正在处理的请求、和处理成功、处理失败的请求。这样当客户端重试的时候,根据情况或者直接返回,或者再次处理。就好像前面说的微信支付的例子。微信支付服务上,需要知道每一笔交易的处理情况,才能正确处理在此转账请求时,是不是需要进行任何动作。
  5. 五是一个系统中需要多层幂等。什么意思呢?A 发送请求给 B,B 处理的一部分是要发送请求给另一个系统 C,C 在处理的过程中还可能需要发请求给另一个系统 D…… D 处理完了返回给 C,C 返回给 B,B 返回给 A。在这个链条中,如果 A B C D 中任何一个系统并没有正确实现幂等,也就是出现了 “幂等漏洞”,那么一个请求还是有可能被多次执行,产生区别于一次执行的影响。

在回到本文的开头,什么是幂等?一个操作如果具有任意多次执行所产生的影响均与一次执行的影响相同,我们就称之为幂等。

这样的语义范畴对行为结果的定义,只有当你的实现中所有的细节都做对了,你才能得到想要的效果。任何一个地方设计有漏洞,或是实现有 Bug,那还是不成。

时间: 2024-11-03 17:47:40

每个工程师都应该了解的:聊聊幂等的相关文章

前端工程师都用哪些靠谱的小工具?

前端工程师都用哪些靠谱的小工具? 转载自 作者 杜Amy 现在市场上可用的前端开发工具实在是数不胜数,令人眼花缭乱,作为一个已入坑的前端开发工程师,再此分享一下自己用过的一些工具库. 前端小工具 说到开发工具,肯定是少不了编辑器: SublimeText SublimeText SublimeText 这个工具很火,关键在于它的小巧.简洁.快枪手,长长的文本打开速度也是杠杠的.具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等.还可自定义键绑定,菜单和工具栏.是一个跨平

每个软件工程师都应该尝试的5件事

回顾我的职业生涯(其实我还没那么老,不过入行确实不少年了),确实有几次人生拐点帮我更具职场智慧,并鞭策我成为软件工程师或程序员,成为那种要么热衷于提高自己的技艺,要么对混入管理层有兴趣,要么只是简单的期望扩大自己的知识面的人.我意识到,鉴于每个人目前的工作情况,有些建议可能并不适合于每一个人,尤其是假如你工作在一家对“谁可以和客户谈话”这种事都作出严格定义的公司的话.所以如果你现在做不到全部这些,也不必烦恼.也要注意,有时,你需要的只是开口去问! 贡献到一个可行的开源项目 除非你与世隔绝,否则一

国内的网络工程师都有谁?

国内的网络工程师都有谁我不敢明确的定义,但是云南网络工程师曹琼值得信赖哦.既然问到了网络工程师中国问题,今天就来回答过内的网络工程师都有谁? 首先,什么叫网络工程师. 网络工程师异别于一般的工程师,比如说造价工程师,质检工程师,建筑工程师等等,网络工程师---顾名思义就是网络(互联网行业)的工程师,也许你很诧异,互联网,写代码,搞优化的,怎么才叫工程师呢?同样的道理,每个行业都有初学者,入门级别的,中介层级的,大神级别的. 网络工程师的定义是什么? 网络工程师是指通过专业的知识系统学习和实战经验

嵌入式工程师都是“匠人”!

就在昨天的沙龙会议上,可以说是受益匪浅,能和大牛级别的牛工交流谈谈关于嵌入式行业的有关问题,然而今天给我印象最深的要是牛工说的"搞嵌入式的工程师都是匠人"做为一个出入行业的人来说真是摸不到头脑啊!为了搞清楚让我们深刻理解更多,牛工还特地给大家写了一份书面的回答,在这里真的要谢谢牛工的细心解答.原文如下:我说的搞嵌入式的工程师是最聪明的,应该还有个限定词是上世纪80年代就介入嵌入式开发的那批人最聪明.原因是:1.他们对嵌入式系统的演变过程最清楚:2.他们对嵌入式系统的体系结构最了解:3.

成为一名优秀的web前端工程师都需要做些什么?

程序设计之道无远弗届,御晨风而返.———— 杰佛瑞 · 詹姆士 我所遇到的前端程序员分两种:    第一种一直在问:如何学习前端?    第二种总说:前端很简单,就那么一点东西.     我从没有听到有人问:如何做一名优秀.甚至卓越的WEB前端工程师.    如果成为一名优秀的web前端工程师(前端攻城师)? 何为:前端工程师?前端工程师,也叫Web前端开发工程师.他是随着web发展,细分出来的行业.Web前端开发技术主要包括三个要素:HTML.CSS和JavaScript!它要求前端开发工程师

运维工程师都需要具备哪些好的技巧?

从当今的社会发展来看,我相信有很多人都会说运维工作是比较苦逼的,其实这也是我们都不能否定的事,有的时候我也是这样感觉的,但是总的来说,在工作的时候什么工作又不是苦的呢?不可能每个人都可以一边挣钱一边玩吧?看看那些在叙利亚前线的记者,在马路上的清洁工,在饭店一直忙碌的厨师,在理发店里两只胳膊永远呆在空中的理发师,不停讲课站立的老师们吧! 如果你现在做的这份工作是和运维.DBA相关的话,不管现状怎么样,是不是应该往好的方向发展呢,在苦逼,乏味,忙碌的工作中寻找一丝乐趣,才能感受到这其中的不一样.有句

运维工程师都在做什么?(转)

首先先看图: 下面是运维工程师至少要能做以下的工作: 1,网络工程师的工作 你至少要能配置CISCO 6509以下的设备,熟悉各种网络协议,否则网络出问题的时候你会傻掉. 2,系统工程师的工作 你至少要理解各种系统服务,在出问题的情况下要迅速解决问题,而不是等系统工程师来解决. 3,安全工程师的工作 我不要求你一定要会各种网络编程,但是在服务器收攻击的情况下,没有防火墙的情况下,做一些简单的处理工作. 4,存储工程师的工作 至少要熟悉各个厂商的设备,各种备份和还原的办法 5,测试工程师的工作 在

黑客和逆向工程师都是这么用Python的

Python灰帽子:黑客与逆向工程师的Python编程之道>是由知名安全机构Immunity Inc的资深黑帽Justin Seitz先生主笔撰写的一本关于编程语言Python如何被广泛应用于黑客与逆向工程领域的书籍.老牌黑客,同时也是Immunity Inc的创始人兼首席技术执行官(CTO)Dave Aitel为本书担任了技术编辑一职. 本书的绝大部分篇幅着眼于黑客技术领域中的两大经久不衰的话题:逆向工程与漏洞挖掘,并向读者呈现了几乎每个逆向工程师或安全研究人员在日常工作中所面临的各种场景,其

嵌入式软件工程师都在开发什么?

在嵌入式这个行业,只要工作了几年的同仁.他们通常在跳槽面试下一家企业的时候简历都写的高大上.十个里面有起码有七个是带水分的.他们为什么会这样呢? 国内嵌入式公司主要有两种: 偏底层芯片公司,偏应用层业务需求公司. 实际上大多数公司都是做应用层业务需求; 比如做人脸识别打卡机的,做GPS导航的,做云终端设备的公司等. 这类的公司,除非已经是非常大规模的,正常是几十号研发在运作. 人脸打卡,人脸识别模块是核心,但是硬件和软件是买的,公司可能制作c++,QT实现上班打卡业务的工作使用场景,数据传输,导