再谈幂等机制

1、什么是幂等性?

幂等性(Idempotence)。在HTTP/1.1规范中幂等性的定义是:前端

Methods can also have the property of “idempotence” in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request.数据库

幂等性:就是用户对于同一操做发起的一次请求或者屡次请求的结果是一致的,不会由于屡次点击而产生了反作用。网络

2、为何须要幂等

那么咱们为何须要接口具备幂等性呢?设想一下如下情形:并发

  • 在App中下订单的时候,点击确认以后,没反应,就又点击了几回。在这种状况下,若是没法保证该接口的幂等性,那么将会出现重复下单问题。
  • 在接收消息的时候,消息推送重复。若是处理消息的接口没法保证幂等,那么重复消费消息产生的影响可能会很是大。

在分布式环境中,网络环境更加复杂,因前端操做抖动、网络故障、消息重复、响应速度慢等缘由,对接口的重复调用几率会比集中式环境下更大,尤为是重复消息在分布式环境中很难避免。分布式

3、如何保证接口的幂等性

接口的幂等性实际上就是接口可重复调用,在调用方屡次调用的状况下,接口最终获得的结果是一致的。有些接口能够自然的实现幂等性,好比查询接口,对于查询来讲,你查询一次和两次,对于系统来讲,没有任何影响,查出的结果也是同样。ide

除了查询功能具备自然的幂等性以外,增长、更新、删除都要保证幂等性。那么如何来保证幂等性呢?高并发

3.1保证幂等策略

幂等须要经过惟一的业务单号来保证。也就是说相同的业务单号,认为是同一笔业务。使用这个惟一的业务单号来确保,后面屡次的相同的业务单号的处理逻辑和执行效果是一致的。
下面以支付为例,在不考虑并发的状况下,实现幂等很简单:①先查询一下订单是否已经支付过,②若是已经支付过,则返回支付成功;若是没有支付,进行支付流程,修改订单状态为‘已支付’。设计

3.2防重复提交策略

上述的保证幂等方案是分红两步的,第②步依赖第①步的查询结果,没法保证原子性的。在高并发下就会出现下面的状况:第二次请求在第一次请求第②步订单状态尚未修改成‘已支付状态’的状况下到来。既然得出了这个结论,余下的问题也就变得简单:把查询和变动状态操做加锁,将并行操做改成串行操做。日志

列举三种改进方式:
一、悲观锁,select for update,整个执行过程当中锁定该订单对应的记录。
二、乐观锁,affectrows = db.update(“update payorder set state=’已支付’ where orderid=$orderid and state=’未支付’ “),若是affectrows=1,执行充值,不然返回已处理。
三、定义防重复表,orderid为unique key或者primary key,执行前,先insert,若insert成功则执行充值,不然返回已处理

4、总结

业务层设计协议时,要求请求方定义不重复的业务流水号。应用实现时,利用数据库乐观锁、插入unique key的日志等方式保证并发时的幂等。
幂等性把关环节,在协议设计评审中,评审重要业务RPC或者http接口是否支持幂等,代码评审中,重点把关请求并发时,是否仍旧可以保证幂等性。设计人员和具体实现人员在实现过程当中,也应该时刻自审幂等性的实现是否过关。
最后介绍一下美团点评开发GTI(它是一个轻量的重复操做关卡系统,它可以确保在分布式环境中操做的惟一性。咱们能够用它来间接保证每一个操做的幂等性),感兴趣能够去研究一下, 20161008112749906

相关文章
相关标签/搜索