qnmd bd:待会劳资就去买个v*n。

web应用中幂等性的学习

 

在平常的工作中经常听到也用到幂等,却没有及时学习总结这个知识点,现在到时候了。

幂等性最初是一个数学上的概念:在某二元运算下,幂等元素是指被自己重复运算(或对于函数是为复合)的结果等于它自己的元素。用公式来表示就是:

\(f(x) = f(f(x))\)

 

数学就是这么抽象,用自己的语言去描述一个概念,置于这个概念的含义有多么丰富就看自己的领会。反正我看到这个是一脸蒙蔽的。高中做这种题目的时候就很蛋疼。

 

如果放在web应用,可以这么理解幂等:就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击(提交请求)而产生了副作用。

 

如果你去网上查关于幂等的博客大多数都是这么讲的。但是我还是觉得这个有点蛋疼。

什么叫"结果一致":比如对于同一个订单来说,第一次支付请求失败了,然后重试第二次支付请求成功了,然后接着又发出了一次支付请求结果成功了。那么这个结果是不是一致的呢?其实,这里的"结果一致"是我理解错了,幂等中的结果不是对于用户来说是否支付成功的状态,而是指的业务上,一个订单至多只能有一个成功的支付请求。

 

所以上面说的可以分析如下几个要点:

同一操作:同一种类型的操作(增,删,改,查),参数要一样。比如,对同一个订单号进行支付就是同一操作,而记录不同时刻的水位就不是同一操作,自己理解一下。

隐含条件:就是这里被坑了一下,编程中由操作失败的时候呀,比如支付;但是\(f(x) = f(f(x))\)只要\(x\)在定义域,\(f(x)\)总是成功的。所以这里操作,其实指的是操作成功,不成功的操作总是幂等的呀,别跟我说成功了一半,去屎吧。所以这里的结果指的是操作成功的结果,不包含失败的结果。这个地方可能有争议,失败也分为很多情况,有的是操作发出去的过程中因网络不通而失败,也可能是处理请求的逻辑失败,所以失败也可能有副作用(修改了状态,或者值)。

结果一致:这个结果是业务中的一种规则,比如通常情况下,一个订单最多只有一个成功的支付请求。假如有一个操作记录表的话,这个成功的操作记录最多也只有一条。

 

 

网上的做法大概有两种:

第一种:使用ticket

  1. 从某个地方(服务,池或者工具类,或者其他什么地方)获取一个ticket
  2. 在调用服务的时候传入这个ticket
  3. 服务在内部处理的时候会先查询这个ticket操作是否存在,如果不存在则说明这个没有被操作过,直接执行;如果发现了这个ticket存在,则直接返回
  4. 服务把结果返回给客户端

 

第二种:查询支付状态,然后再决定是否去更新

 

这两种方法都会导致并发问题:

这两个方法都有一个问题,以方法一为例:
根据ticket查询此次操作是否存在,如果存在则表示该操作已经执行过,直接返回结果;如果不存在,支付扣款,保存结果
如果第二次调用的时候第一次正在处理,但是没有处理完,第二次怎么去返回结果?或者说第二次在查询此次操作的时候是不是查不到第一次的操作?
方法二也是一样的,先查后支付,那两次同时调用都查到没有支付然后去扣款,还是有并发的问题

 

解决这个并发问题有人提出了用分布式锁。所以分布式锁怎么实现呢?

 

引出话题:

  1. 订单和支付系统的设计
  2. 分布式锁

相关文章: