幂等性:就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。举个最简单的例子,那就是支付,用户购买商品后支付,支付扣款成功,但是返回结果的时候网络异常,此时钱已经扣了,用户再次点击按钮,此时会进行第二次扣款,返回结果成功,用户查询余额发现多扣钱了,流水记录也变成了两条。在以前的单应用系统中,我们只需要把数据操作放入事务中即可,发生错误立即回滚,但是再响应客户端的时候也有可能出现网络中断或者异常等等。
在增删改查4个操作中,尤为注意就是增加或者修改,查询对于结果是不会有改变的,删除只会进行一次,用户多次点击产生的结果一样,修改在大多场景下结果一样,增加在重复提交的场景下会出现。
那么如何设计接口才能做到幂等呢?
方法一:单次支付请求,也就是直接支付了,不需要额外的数据库操作了,这个时候发起异步请求创建一个唯一的ticketId,就是门票,这张门票只能使用一次就作废,具体步骤如下:
1、异步请求获取门票
2、调用支付,传入门票
3、根据门票ID查询此次操作是否存在,如果存在则表示该操作已经执行过,直接返回结果;如果不存在,支付扣款,保存结果
4、返回结果到客户端
如果步骤4通信失败,用户再次发起请求,那么最终结果还是一样的.
方法二:分布式环境下各个服务相互调用
这边就要举例我们的系统了,我们支付的时候先要扣款,然后更新订单,这个地方就涉及到了订单服务以及支付服务了。用户调用支付,扣款成功后,更新对应订单状态,然后再保存流水。而在这个地方就没必要使用门票ticketId了,因为会比较闲的麻烦(支付状态:未支付,已支付)
步骤:
1、查询订单支付状态
2、如果已经支付,直接返回结果
3、如果未支付,则支付扣款并且保存流水
4、返回支付结果
如果步骤4通信失败,用户再次发起请求,那么最终结果还是一样的
对于做过支付的朋友,幂等也可以称之为冲正,保证客户端与服务端的交易一致性,避免多次扣款。
以下为接口文档对于幂等的描述,通过请求id号来判断是否为同一个请求。
<li class="tool-item tool-active is-like "><a href="javascript:;"><svg class="icon" aria-hidden="true"> <use xlink:href="#csdnc-thumbsup"></use> </svg><span class="name">点赞</span> <span class="count">4</span> </a></li> <li class="tool-item tool-active is-collection "><a href="javascript:;" data-report-click="{"mod":"popu_824"}"><svg class="icon" aria-hidden="true"> <use xlink:href="#icon-csdnc-Collection-G"></use> </svg><span class="name">收藏</span></a></li> <li class="tool-item tool-active is-share"><a href="javascript:;"><svg class="icon" aria-hidden="true"> <use xlink:href="#icon-csdnc-fenxiang"></use> </svg>分享</a></li> <!--打赏开始--> <!--打赏结束--> <li class="tool-item tool-more"> <a> <svg t="1575545411852" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5717" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M179.176 499.222m-113.245 0a113.245 113.245 0 1 0 226.49 0 113.245 113.245 0 1 0-226.49 0Z" p-id="5718"></path><path d="M509.684 499.222m-113.245 0a113.245 113.245 0 1 0 226.49 0 113.245 113.245 0 1 0-226.49 0Z" p-id="5719"></path><path d="M846.175 499.222m-113.245 0a113.245 113.245 0 1 0 226.49 0 113.245 113.245 0 1 0-226.49 0Z" p-id="5720"></path></svg> </a> <ul class="more-box"> <li class="item"><a class="article-report">文章举报</a></li> </ul> </li> </ul> </div> </div> <div class="person-messagebox"> <div class="left-message"><a href="https://blog.csdn.net/miachen520"> <img src="https://profile.csdnimg.cn/C/B/4/3_miachen520" class="avatar_pic" username="miachen520"> <img src="https://g.csdnimg.cn/static/user-reg-year/2x/4.png" class="user-years"> </a></div> <div class="middle-message"> <div class="title"><span class="tit"><a href="https://blog.csdn.net/miachen520" data-report-click="{"mod":"popu_379"}" target="_blank">mischen520</a></span> </div> <div class="text"><span>发布了469 篇原创文章</span> · <span>获赞 70</span> · <span>访问量 82万+</span></div> </div> <div class="right-message"> <a href="https://bbs.csdn.net/topics/395530962" target="_blank" class="btn btn-sm btn-red-hollow bt-button personal-messageboard">他的留言板 </a> <a class="btn btn-sm bt-button personal-watch" data-report-click="{"mod":"popu_379"}">关注</a> </div> </div> </div>