接口幂等性

一、什么是幂等性
“幂等”是指一个操作重复执行N次得到的结果(副作用)与执行一次是相等的。

例如: 在HTTP协议中,get请求,会得到同样的数据

bool get_money(id, amount)
1
    参数:
        id:用户的账户
        amount: 表示取多少钱
    返回值:
        true: 表示取钱成功
        false: 表示取钱失败
情景一:
    1、一位用户A 取100块钱, 这个请求,发送到了服务器
    2、服务器正常的处理了这个请求,把用户A的总额,减去了100块钱, 这时,服务器把处理结果返回给客户端。
    3、服务器把处理结果,返回给客户端,可是这时,由于网络不稳定, 导致客户端没有接受到服务器返回的处理结果,这时,用户(或者客户端)进行重试,同样的请求又到服务器,服务器又在用户A的总额中,减去了100块钱........
    用户A 取了100块钱, 银行却扣了 200.................

这个问题的解决方案是:
客户端在调用这个接口,传入一个流水号,

bool get_money(id, amount, serial_number)

 对于同一个操作(同一笔业务)流水号不变(在不同操作中,必须保证流水号的唯一性),
 这时,如果服务器遇到上面那种情况,只需要判断客户端传过来的这个流水号,是否已经操作(处理)过了,如果已经处理过了,就直接把处理结果返回给客户端
 这样,就不存在上面的问题了
 

概述

幂等性原本是数学上的概念,即使公式:f(x)=f(f(x)) 能够成立的数学性质。用在编程领域,则意为对同一个系统,使用同样的条件,一次请求和重复的多次请求对系统资源的影响是一致的

幂等性是分布式系统设计中十分重要的概念,具有这一性质的接口在设计时总是秉持这样的一种理念:调用接口发生异常并且重复尝试时,总是会造成系统所无法承受的损失,所以必须阻止这种现象的发生

幂等有两个维度:一是空间维度上的幂等,即幂等对象的范围,是个人还是机构,是某一次交易还是某种类型的交易...二是时间维度上的幂等,即幂等的保证时间,是几秒、几分钟还是永久性的...

不同的需求,会有不一样的解决方案,难度和成本也不一样。

幂等性适用领域

试想这样的一种场景:在电商平台上支付后,因为网络原因导致系统提示你支付失败,于是你又重新付款了一次,等完成后检查网银发现被系统扣了两次款,这是一种什么样的体验?

造成上述问题的原因可能有很多,比如第一次付款时实际支付成功,但是信息返回时网络中断导致系统误判;又比如第一次付款的确失败了,但第二次付款时发生意外,导致支付请求被重复发送等等。在一次支付的过程中,每个环节都有可能会发生问题,我们要如何规避这类问题引发的风险?

幂等性是解决这类问题的方案之一,所以在电商,银行,互联网金融等对数据准确性要求很高的领域中,这一特性具有十分重要的地位。

幂等的常用思路

1. MVCC:####

多版本并发控制,乐观锁的一种实现,在数据更新时需要去比较持有数据的版本号,版本号不一致的操作无法成功。例如博客点赞次数自动+1的接口:

public boolean addCount(Long id, Long version);

 

update blogTable set count= count+1,version=version+1 where id=321 and version=123 

每一个version只有一次执行成功的机会,一旦失败必须重新获取。

2. 去重表:####

利用数据库表单的特性来实现幂等,常用的一个思路是在表上构建唯一性索引,保证某一类数据一旦执行完毕,后续同样的请求再也无法成功写入。

例子还是上述的博客点赞问题,要想防止一个人重复点赞,可以设计一张表,将博客id与用户id绑定建立唯一索引,每当用户点赞时就往表中写入一条数据,这样重复点赞的数据就无法写入。

3. TOKEN机制:####

这种机制就比较重要了,适用范围较广,有多种不同的实现方式。其核心思想是为每一次操作生成一个唯一性的凭证,也就是token。一个token在操作的每一个阶段只有一次执行权,一旦执行成功则保存执行结果。对重复的请求,返回同一个结果。

以电商平台为例子,电商平台上的订单id就是最适合的token。当用户下单时,会经历多个环节,比如生成订单,减库存,减优惠券等等。

每一个环节执行时都先检测一下该订单id是否已经执行过这一步骤,对未执行的请求,执行操作并缓存结果,而对已经执行过的id,则直接返回之前的执行结果,不做任何操作。这样可以在最大程度上避免操作的重复执行问题,缓存起来的执行结果也能用于事务的控制等。

总结

幂等性是分布式领域的一把利刃,每一个有志与分布式领域的程序员都应该熟悉它的设计思想。

另外,幂等性接口的设计方案有如下几种:

1、乐观锁

多版本并发控制,该策略主要使用 update with condition(更新带条件来防止)来保证多次外部请求调用对系统的影响是一致的。

在系统设计的过程中,合理的使用乐观锁,通过 version 或者 updateTime(timestamp)等其他条件,来做乐观锁的判断条件,这

样保证更新操作即使在并发的情况下,也不会有太大的问题

2、Token机制,防止页面重复提交

数据提交前要向服务的申请 token,token 放到 redis 中,设置token 有效时间

客户端每次在调用接口的时候,需要在请求头中,传递令牌参数,每次令牌只能用一次,提交数据后后台校验 token,同时删除

token,生成新的 token 返回

3、数据库唯一索引

特殊的表单,可以使用数据唯一索引,重复插入报错,进行限制重复提交
 

发布了19 篇原创文章 · 获赞 13 · 访问量 8195
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览