创建订单实现幂等的一点思考

标签: IT技术 分布式 架构设计 | 发表时间:2018-04-10 11:20 | 作者:Sam哥哥
出处:http://blog.jobbole.com

幂等的概念

大部分文章都会说,同一个操作,进行多次操作后,结果是一样的,就可以说这个操作是支持幂等的。感觉不太准确,比如一个http get操作,可能每次的结果都不一样,但是其实是幂等的。看了很多文章,感觉下面的定义比较准确:

一个操作如果多次任意执行所产生的影响(或者叫副作用),都是相同的。

创建订单的幂等

如果一个用户分两次下单,购买的商品都是一样的。

第一次请求:user1:购买一个商品product1;
第二次请求:user1:还是购买一个商品product1;

这种场景也很常见,是需要生成两个订单的。这样子看起来貌似创建订单的接口做不了幂等,因为业务数据一样的情况下,还是需要生成多个订单。但是这样子设计还是有个坑,万一创建订单的接口超时了呢?并且调用方进行了重试的话,那就可能变成用户其实想下一个单,但是订单系统其实生成了多个订单。比如说:

调用方发起创建订单的请求,订单系统收到了,并成功创建订单了。但是由于系统原因或者网络原因等,没有及时告知调用方订单已经创建成功,调用方一直等待回复,直到超时了。调用方再次发起了创建订单的请求,这个时候就可能会生成多个订单。

如果订单接口不支持幂等的情况下,如何应付这种情况呢?有两种方法

第一种:

当调用方调用订单接口超时了,是会收到异常的,这个时候调用方捕获到这个异常后, 不要进行重试操作了,调用订单的一个回滚接口,将订单取消掉。虽然看起来很low,但是还是有人这么做的。

第二种:

让订单系统提供一个订单是否创建成功的查询接口,根据一些关键业务字段去查询,如果查询到已经创建成功了,则调用方不要重试了。

上面两种方案都有人用过,但是都没实现幂等。其实针对上面的场景,用幂等来设计也不是很难。可以使用一个唯一的流水号ID,用来标识是不是同一个请求或者交易。这种ID通常都需要具备 全局唯一性。假设让客户端来生成这个ID,每个创建订单的请求生成一个唯一的ID。那么订单系统如何根据来实现幂等呢?通常有两种。

第一种:

先将这个ID保存到一个流水表里面,并且流水表中将这个ID设置为 UNIQUE KEY,如果插入出现冲突了,则说明这个创建订单的请求已经处理过了,直接返回之前的操作结果。

第二种:

根据ID读取流水表,如果没有读取到,则创建订单和插入流水表。如果读取到了,则返回之前的操作结果。

不建议使用第二种方式,因为大部分情况下的请求都不是重试来的,让100%的请求都要去读取流水表,实在是不应该。另外,读取流水表的操作也是有潜在风险的,因为用数据库的读检查来确保数据存在性可能因为竞争而不生效,存在竞态条件。

建议用第一种方案,因为本来流水表就是要插入,顺便利用 UNIQUE KEY的冲突特性来判断。

现在我们用第一种方案完整描述一下整个处理过程。

当调用方携带流水号ID调用创建订单的接口,如果出现超时了,调用方不知道订单到底创建成功还是失败,这个时候,用 同一个流水号进行重试,订单系统虽然收到了两个请求,但是由于流水号ID是同一个,可以根据流水表来做幂等操作。并告知对方订单创建成功与否。

这里又有一个坑,万一调用方进行重试的时候,重新生成一个流水号,那就没得救了,会生成多个订单了。这个只能让客户端来保证了。

关于多重幂等

假设创建订单的接口在创建订单的时候,还需要依赖一些外部系统,如果订单创建接口实现了幂等,但是外部接口没有实现幂等的话,还是可能出现 幂等漏洞。属于整个链路幂等的问题了。好复杂。目前还没想好如何处理这种情况呢。

思考题

调用方创建唯一ID,服务端用流水表这种方式实现幂等,非常依赖这个唯一ID。万一这个ID丢失了呢?咋破?目前我也在思考这个问题。

创建订单实现幂等的一点思考,首发于 文章 - 伯乐在线

相关 [幂等 思考] 推荐:

创建订单实现幂等的一点思考

- - 文章 – 伯乐在线
大部分文章都会说,同一个操作,进行多次操作后,结果是一样的,就可以说这个操作是支持幂等的. 感觉不太准确,比如一个http get操作,可能每次的结果都不一样,但是其实是幂等的. 看了很多文章,感觉下面的定义比较准确:. 一个操作如果多次任意执行所产生的影响(或者叫副作用),都是相同的. 如果一个用户分两次下单,购买的商品都是一样的.

电商课题:幂等性

- - 博客园_旁观者
幂等性的数学表达:f(f(x)) = f(x). 幂等性是系统接口对外的一种承诺. 幂等性指的是,使用相同参数对同一资源重复调用某个接口的结果与调用一次的结果相同. 幂等性的一个实现是,使你的接口必须返回 0(成功),即使这时资源或动作已经停止并且无工作要完成. 防范 POST 重复提交. HTTP POST 操作既不是安全的,也不是幂等的(至少在HTTP规范里没有保证).

HTTP幂等性概念和应用

- rockmaple - 酷壳 - CoolShell.cn
[ 感谢 Todd 同学投递本文 ]. 基于HTTP协议的Web API是时下最为流行的一种分布式服务提供方式. 无论是在大型互联网应用还是企业级架构中,我们都见到了越来越多的SOA或RESTful的Web API. 为什么Web API如此流行呢. 我认为很大程度上应归功于简单有效的HTTP协议.

终极思考

- wei - 牛博国际
我的海淀剧院演讲门票放出后,八小时卖了四百多张,同事们说,日. 我淡淡地说,别这样,也许正是因为便宜才这么好卖嘛. 一转身我马上就打电话给老婆,操. 早知道就他妈把票价定高一点啦,真倒霉......干. 很大程度上,这可以解释两件事:1.为什么已婚事业男性的健康状况会相对好一些. 2.为什么在社会上受到尊重和认可的事业男性在老婆的眼里都是傻逼.

分布式幂等问题解决方案三部曲

- - SegmentFault 最新的文章
文章目的:本文旨在提炼一套分布式幂等问题的思考框架,而非解决某个具体的分布式幂等问题. 在这个框架体系内,会有一些方案举例说明. 文章目标:希望读者能通过这套思考框架设计出符合自己业务的完备的幂等解决方案. (1)背景介绍,为什么会有幂等. (2)什么是幂等,这个定义非常重要,决定了整个思考框架. (3)解决幂等问题的三部曲,也是作者的思考框架.

Kafka笔记—可靠性、幂等性和事务 - luozhiyun - 博客园

- -
这几天很忙,但是我现在给我的要求是一周至少要出一篇文章,所以先拿这篇笔记来做开胃菜,源码分析估计明后两天应该能写一篇. Kafka只对“已提交”的消息(committed message)做有限度的持久化保证. 当Kafka的若干个Broker成功地接收到一条消息并写入到日志文件后,它们会告诉生产者程序这条消息已成功提交.

高并发下如何保证接口的幂等性?

- -
接口幂等性问题,对于开发人员来说,是一个跟语言无关的公共问题. 本文分享了一些解决这类问题非常实用的办法,绝大部分内容我在项目中实践过的,给有需要的小伙伴一个参考. 不知道你有没有遇到过这些场景:. form表单时,保存按钮不小心快速点了两次,表中竟然产生了两条重复的数据,只是id不一样. 接口超时问题,通常会引入了.

Kafka幂等性原理及实现剖析 - 哥不是小萝莉 - 博客园

- -
最近和一些同学交流的时候反馈说,在面试Kafka时,被问到Kafka组件组成部分、API使用、Consumer和Producer原理及作用等问题都能详细作答. 但是,问到一个平时不注意的问题,就是Kafka的幂等性,被卡主了. 那么,今天笔者就为大家来剖析一下Kafka的幂等性原理及实现. 2.1 Kafka为啥需要幂等性.

动车追尾的思考

- David Ruan - 扬韬
1、两列运行的动车追尾,绝对属于重特大责任事故. 雷电导致前车失灵,已经是责任事故了. 前车失灵,信号没有外发,又是责任事故. 调度体系没有发觉列车失灵,也是责任事故. 后车没有察知前车失灵,还是责任事故. 最后,后车发现问题,紧急制动系统有没有用也值得怀疑,因为后车司机据说是人工制动并殉职于岗位的.

重新思考电子书

- Alex - 爱范儿 · Beats of Bits
Hart,“古登堡计划”发起人,2011 年 9 月 6 日去世,享年 64 岁. 从 1971 年 Hart 制作第一本电子书,启动“古登堡计划”开始到 2011 年,Kindle、Nook 流行,正好经过 40 年. 如今电子书阅读器、电子书变得越来越流行,在北京的地铁上,你会经常看见低头拿着 Kindle、Nook、iPad、汉王的人们.