幂等的概念


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

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


创建订单的幂等


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

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

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

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

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

第一种:

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

第二种:

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

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

第一种:

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

第二种:

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

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

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

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

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

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


关于多重幂等


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


思考题


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

创建订单实现幂等的一点思考相关推荐

  1. python多线程队列处理_Python线程和队列使用的一点思考

    Python线程和队列使用的一点思考 1. 斗哥采访环节请问为什么要使用线程? 答:为了提高程序速度,代码效率呀. 请问为什么要使用队列? 答:个人认为队列可以保证线程安全,实现线程间的同步,比较稳. ...

  2. 关于前端职业规划的一点思考

    自己目前已经工作3年了,最近也刚换了新工作,日常也一直在考虑自己的前端职业规划到底是怎样的,目前个人视角还不是很宽广,怕误人子弟,以下这篇文章有点启发,故转发供大家借鉴(里面有部分内容做了一些小修改) ...

  3. 关于优质博客聚合的一点思考

    前言 随着互联网时代的到来,我们发现知识的获取不再像历史上任何一个时代那么复杂,而是变得十分的简单.互联网每天都在产生巨大的信息,这些信息又多又杂,可谓是知识的海洋,太多优质的内容就这样悄无声息的被淹 ...

  4. 对zebra的一点思考Think_Of_ZEBRA

    目录 对zebra的一点思考(Think Of ZEBRA 对zebra的一点思考(Think Of ZEBRA 此文并不针对zebra的应用,甚至不是一个架构的分析,只是对于Zebra的一点儿思考. ...

  5. 防止重复请求提交创建订单等解决方案

    背景: 在开发产品,交付给用户使用之后,重复提交的现象偶尔或经常出现.开发人员觉得数据重复,用户觉得订单多了一个,产品觉得有bug.这可不是好现象. 下面以创建订单为例: 原因: 1.误操作两次点击下 ...

  6. TCC 强一致性 实时 DEMO 下单(创建订单,扣除库存,增加积分,扣除余额)

    伪代码 场景 用购买某种商品1件(原库存1000),增加20积分,扣除100元余额 设计说明 通过日志表来完成TCC.修改库存,余额表要先添加一条记录到他们的日志表里,表要记录TCC状态. 通过唯一业 ...

  7. mysql 手动写时间_关于数据库中如何存储时间的一点思考

    1.切记不要用字符串存储日期 我记得我在大学的时候就这样干过,而且现在很多对数据库不太了解的新手也会这样干,可见,这种存储日期的方式的优点还是有的,就是简单直白,容易上手. 但是,这是不正确的做法,主 ...

  8. ajax 提交订单,php-在Woocommerce 3中通过ajax提交并在结帐时创建订单

    我在结帐表单中添加了一个按钮: 并在functions.php文件中添加了一个AJAX代码段: add_action('wp_head', 'ajax_call_place_order'); func ...

  9. 对于表列数据类型选择的一点思考

    对于表列数据类型选择的一点思考 简介 SQL Server每个表中各列的数据类型的选择通常显得很简单,但是对于具体数据类型的选择的不同对性能的影响还是略有差别.本篇文章对SQL Server表列数据类 ...

最新文章

  1. RHEL7 kvm虚拟机桥接网络配置
  2. 企业网站常用中英文对照表
  3. 北航计算机网络 传输层实验,北航研究生计算机网络实验_实验七 传输层实验
  4. 华为云战略投入政企市场,发布华为云Stack
  5. 12.IDA-虚函数和虚表(vf代表虚函数,vf3代表this指向第三个函数)
  6. Wamp安装后环境搭建(WampServer Version 2.2)
  7. [IC]Lithograph(1)光刻技术分析与展望
  8. 4412开发板团购活动
  9. PMP课程笔记:第8章 项目质量管理
  10. MQTT和CoAP对比
  11. Python笔记:re模块详解
  12. selenium与firefox、 chrome版本对应关系
  13. 计算机重装后如何连接无线网络,电脑重装系统后怎么连接无线网络连接
  14. .so文件(so文件是什么)
  15. alooa是华为什么型号_dubalooa什么型号手机 dubalooa华为手机什么型号 - 云骑士一键重装系统...
  16. 移动vue大转盘抽奖
  17. mysqldump 备份报 Warning: A partial dump from a server that has GTIDs will by default include the..
  18. 黑盒测试用例设计方法-正交试验
  19. mysql 5.6.21 winx64_mysql-advanced-5.6.21-winx64部署及使用
  20. 3D NAND 前沿

热门文章

  1. Vista系统安装CCTVBox插件出错解决方法
  2. FLYGON.NET(以及本人所有博客)赞助名单 2016~2018
  3. 【ACO三维路径规划】基于matlab蚁群算法无人机三维路径规划【含Matlab源码 1278期】
  4. 大数据工具——oozie调度
  5. 开播了!大行都在用的最新反欺诈技术大揭密!
  6. 游戏引擎Flax Engine源码分析(十)渲染
  7. 208个最新最全大数据/人工智能专有名词术语 中英对照
  8. c语言resource files的作用,VC中Source Files, Header Files, Resource Fil
  9. 微信小程序入门7--传感器设备综合使用
  10. 最详细的Hadoop+Hbase+Hive完全分布式环境搭建教程(二)