最近不少人都在谈论幂等性,好吧,这回我也来聊聊这个话题,光看着俩字,一开始的确有点一头雾水,语文很差嘛,词太专业嘛,对吧数据库
现现在咱们的系统大多拆分为分布式SOA,或者微服务,一套系统中包含了多个子系统服务,而一个子系统服务每每会去调用另外一个服务,而服务调用服务无非就是使用RPC通讯或者restful,既然是通讯,那么就有可能再服务器处理完毕后返回结果的时候挂掉,这个时候用户端发现好久没有反应,那么就会屡次点击按钮,这样请求有屡次,那么处理数据的结果是否要统一呢?那是确定的!尤为再支付场景。服务器
幂等性:就是用户对于同一操做发起的一次请求或者屡次请求的结果是一致的,不会由于屡次点击而产生了反作用。举个最简单的例子,那就是支付,用户购买商品使用约支付,支付扣款成功,可是返回结果的时候网络异常,此时钱已经扣了,用户再次点击按钮,此时会进行第二次扣款,返回结果成功,用户查询余额返发现多扣钱了,流水记录也变成了两条...restful
在之前的单应用系统中,咱们只须要把数据操做放入事务中便可,发生错误当即回滚,可是再响应客户端的时候也有可能出现网络中断或者异常等等。网络
在增删改查4个操做中,尤其注意就是增长或者修改,异步
查询对于结果是不会有改变的,分布式
删除只会进行一次,用户屡次点击产生的结果同样微服务
修改在大多场景下结果同样设计
增长在重复提交的场景下会出现rest
那么如何设计接口才能作到幂等呢?blog
方法1、单次支付请求,也就是直接支付了,不须要额外的数据库操做了,这个时候发起异步请求建立一个惟一的ticketId,就是门票,这张门票只能使用一次就做废,具体步骤以下:
异步请求获取门票
调用支付,传入门票
根据门票ID查询这次操做是否存在,若是存在则表示该操做已经执行过,直接返回结果;若是不存在,支付扣款,保存结果
返回结果到客户端
若是步骤4通讯失败,用户再次发起请求,那么最终结果仍是同样的
方法2、分布式环境下各个服务相互调用
这边就要举例咱们的系统了,咱们支付的时候先要扣款,而后更新订单,这个地方就涉及到了订单服务以及支付服务了。
用户调用支付,扣款成功后,更新对应订单状态,而后再保存流水。
而在这个地方就不必使用门票ticketId了,由于会比较闲的麻烦
(支付状态:未支付,已支付)
步骤:
一、查询订单支付状态
二、若是已经支付,直接返回结果
三、若是未支付,则支付扣款而且保存流水
四、返回支付结果
若是步骤4通讯失败,用户再次发起请求,那么最终结果仍是同样的
对于作过支付的朋友,幂等,也能够称之为冲正,保证客户端与服务端的交易一致性,避免屡次扣款。
最后来看一下咱们的订单流程,虽然不是很复杂,可是最后在支付环境是必定要实现幂等性的