幂等性

发布时间 2023-06-25 17:16:53作者: 朝云出岫

1、含义

对资源一次或多次请求所产生的结果是相同的(网络超时情况除外),也就是说一次或多次请求对资源的影响是相同的。

可以说,幂等性要求在请求成功的情况下,多次请求对系统的影响是一致的,并不会因为哪一次请求,导致不同的结果或影响。

2、常见的幂等性操作

在DML中,某些语句可以体现出幂等性:

   select * from user where id = 1    // 保持幂等性

   update user set name = 'tom' where id = 1    // 保持幂等性

   delete * from user where id = 1    // 保持幂等性

   update user set  age = age + 1 where id = 1    // 不保持幂等性

3、常见场景

在支付系统中,因为网络原因请求无法到达,或者前端操作抖动等原因,导致支付请求多次重复提交;又或者退款申请的多次调用等;服务的相应接口都需要保持幂等性,以防止产生副作用,即出现系统数据状态改变,导致数据错误。

4、实现方法

1)乐观锁

一般给某条数据加上version字段,在每次更新该数据时,version自增1:

update user set name = 'Joe' , version = version + 1 where id = 1 and version = #{version}

2) 去重索引

对于订单,可以在表中建立关于订单号orderNo的唯一索引,当多次相同订单号的订单请求到达时,数据库会因为唯一索引兜底,保证只有一个请求执行成功。

3)分布式锁

 

一般借助redis锁来实现幂等性,对于支付订单,当支付请求到达时,根据orderNo设置redis锁,等待请求完成后再释放锁。在加锁后,判断订单的是否已存在,且其支付状态如何,做出相应的处理。使用redis锁(缓存)的好处是效率比唯一索引去重高。

4)token令牌

分为两步:申请token并存入redis中,下单请求。

在下单请求时,将申请的token传入header,判断header中的token作为key是否在redis中存在;如果存在,则删除该key(判断存在和删除该key必须为原子操作),并执行业务逻辑;如果不存在,则请求是非法的。关键点在于只能申请一次token,保障了幂等性。

5)状态机

每一次操作会导致资源处于不同的状态上,当在某一种状态上,只能执行特定的操作。

5. 参考博客文档:

https://www.cnblogs.com/javalyy/p/8882144.html(这篇博文写得不错)

https://www.cnblogs.com/dongl961230/p/14817223.html