一、概述
幂等性定义:
用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。【同一操作指的是同一个浏览器
,发送相同的请求】。
常见场景:
提交订单接口
。返回提交结果时网络出现故障,再次提交订单,出现同一订单多次提交问题;支付订单接口
。用户购买商品使用约支付,支付扣款成功,但是返回结果的时候网络异常,此时钱已经扣了,用户再次点击按钮,此时会进行第二次扣款,返回结果成功,用户查询余额返发现多扣钱了,流水记录也变成了两条,是有问题的。
注意:
并不是所有接口都要求幂等性,要根据业务而定。
二、幂等性策略分析
核心思想:
通过唯一的业务号
保证幂等
通用实现方案:
1. 非并发情况下,查询唯一业务单号有没有操作过,没有则执行操作;
2. 并发情况下,整个操作过程加分布式锁。
三、不同行为幂等性分析
3.1 Select操作
不会对业务数据有影响,天然幂等。
3.2 Delete操作
存在唯一业务号场景:
- 第一次delete后,第二次继续delete,由于第一次已经删除,第二次直接delete会返回0,天然支持幂等;
- 第二次delete之前,先查询是否存在该数据,然后再进行删除。
不存在唯一业务号场景:
例如:批量删除审核未通过的商品
第一次删除之后,在第二次删除之前,又插入了一个条新的审核未通过的商品,是否删除,需要根据业务进行判断?如果需要保持幂等性,即不能删除新审核未通过商品,利用Token机制+分布式锁
来解决
3.3 Update操作
存在唯一业务号场景:
又分为两种场景:1.仅设置值场景;2.设置自增值场景,每次执行都会导致某个字段+1
1. 设置值场景:天然幂等的;
2. 设置自增值场景:利用乐观锁增加版本号来解决
不存在唯一业务号场景:
利用Token机制 + 分布式锁来解决。
3.4 Insert操作
存在唯一业务号场景:
例如秒杀,订单ID+用户ID是唯一业务号
- 利用分布式锁,保证接口幂等;
- 将订单ID+用户ID在数据库层面设为
唯一索引
,这样保证了数据唯一性,也就保证了接口幂等性。
不存在唯一业务号场景:
例如用户注册。利用Token机制 + 分布式锁
来解决。
3.5 混合操作
业务过程中存在多个insert或update请求。总体上采用Token机制和分布式锁
来解决。
存在唯一业务号场景:
例如:秒杀,订单ID+用户ID是唯一业务号
利用分布式锁,保证接口幂等
不存在唯一业务号场景:
利用Token机制 + 分布式锁来解决。
四、Token机制实现接口幂等性方案
利用分布式锁+Token机制保证了接口幂等性,Token主要用来保证来自同一个请求的。主要流程为:
- 首先调用获取Token接口。利用UUID生成Token,并以当前会话SessionId作为key,Token作为value放入到Redis中。设置超时时间;
- 其次,请求头或请求参数中传入获取的Token。根据当前SessionId去Redis获取存储的Token和请求传入的Token进行对比;
- 最后,获取Token时,可能存在并发情况,因此,需要加分布式锁。