一、什么是幂等性?
幂等(idempotence),来源于数学中的一个概念,例如:幂等函数/幂等方法(指用相同的参数重复执行,并能获得相同结果的函数,这些函数不影响系统状态,也不用担心重复执行会对系统造成改变)。
通俗来说:就是多次调用对系统的产生的影响是一样的,即对资源的作用是一样的。
幂等性,强调的是外界通过接口对系统内部的影响, 只要一次或多次调用对某一个资源应该具有同样的副作用就行。
二、为什么出现幂等性?
非幂等的重要因素是重复提交引起的,一般情况下,接口调用时都能正常返回信息,不会重复提交,但遇见以下情况时就可能会出现问题,常见的场景如下:
- 因网络波动,用户重复提交请求
- 用户恶意进行刷单行为
- 接口超时重试请求
- 定时任务重试
- 使用消息队列时,重复消费现象
三、解决方案
方案1:防重Token令牌实现幂等
此方案包含两个请求阶段:
1.客户端请求服务端申请获取token。
2.客户端携带token再次请求,服务端校验token后进行操作。
方案2:分布式锁
分布式锁的逻辑是,每次请求都通过业务唯一ID来尝试获取锁,如果获取成功,就进行后续业务逻辑操作,如果获取失败,就舍弃请求直接返回。
分布式锁通常是基于redis来实现的。
方案3:悲观锁实现幂等性
悲观锁的实现,往往依靠数据库提供的锁机制,具有强烈的独占和排他特性。
通过mysql 的sql 语句 for update 可以锁住数据;
select * from account where id = 123 for update;
方案4:数据库乐观锁实现幂等性
数据库乐观锁方案适用于执行更新操作,通过为数据库表增加一个 “version” 字段来实现。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号等于数据库表当前版本号,则予以更新,否则认为是过期数据。
update account set amount=amount-50,version=version+1
where id=123 and version = 1;