幂等概念以及非幂等的解决方案

目录

1、幂等的概念

2、什么情况会出现接口幂等性问题?

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

前端方案

后端方案

1)数据库表创建唯一性索引

2)Redis-Token机制

 3)使用Post/Redirect/Get模式

4)使用数据库乐观锁


1、幂等的概念

我们在对外暴露接口时,这个接口往往会被调用多次,而多次被调用和被调用一次所造成的影响一样的话,这个现象就称为幂等。

幂等函数,幂等接口,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数,对数据的影响是一样的。

注意:这里强调的是产生的影响是一样的,而不是结果一样。比如你一次插入请求插入一条数据,产生的影响是多一条记录,多次插入请求产生的影响如果产生的影响也是多一条数据,那么就是幂等的,而不是说一次插入的一条数据和多次插入的数据结果一样。

2、什么情况会出现接口幂等性问题?

非幂等是指同一个系统,同样的参数条件,一次请求和多次同样重复的请求对资源的影响不一样。

1)用户重复操作:用户提交请求进行创建订单操作,如果由于网络问题,导致页面一直在转,用户重新点击创建订单按钮,这时,上一个请求刚执行完。由于是重复点击创建订单,所以两个订单的参数是一样的,如果没有解决非幂等问题的话,就会导致同样的订单在数据库中创建了两条,这样肯定是不合适的。一次请求产生一条记录,多次一样的请求应该也产生产生一条记录才是幂等的,但是它产生了多条一样的记录。这样肯定不合适。

2)因网络波动,而引起重复的请求

3)应用使用了失败或超时重试机制(如Nginx重试、RPC重试或业务层重试等)

4)页面重复刷新,提交请求

5)  使用浏览器后退按钮重复之前的操作

6)定时任务重复执行

..........

总之就是发送了多次同样的请求,所以我们必须解决幂等性问题,尤其是哪些会影响变更数据的接口,更要保证接口的幂等性。

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

为了保证接口的幂等性,可以采用以下几种方案。

前端方案

按钮只可操作一次,一般是提交后,就把置灰等,让用户不可按。但是这种不可靠,只能简单看看。

后端方案

1)数据库表创建唯一性索引

比如数据插入类insert的场景,就可以给数据库表业务字段添加唯一性的约束,这样同样的数据就不能插入两遍,就能保证不管你同样的请求执行多少次,我数据库中就只有唯一一条记录。

2)Redis-Token机制

客户端在发送请求之前,请求后端获取一个唯一的token凭证(一般是一个唯一的ID),同时将这个token存到redis中(系统为分布式架构?存在redis:可保存在jvm缓存中),然后将这个token返回给客户端;

接着客户端在发送业务请求时,都携带着这个token,后端接收到业务请求后,先验证这个token是否在redis中有,如果有则delete删除这个token,并执行业务逻辑;如果这个token没有,表示这个业务已经执行过了,则不做任何操作,返回业务已执行完毕的信息给客户端。

 注意:必须保证,从redis中:查询token判断、删除token两个操作的原子性。因为在高并发的情况下,A请求执行到查询token判断有,还没到删除token时间片就没了,这时要切到B请求进来进行查询token判断,发现有token,就会执行业务逻辑,等B请求的时间片到了,切到A请求继续,因为A请求之前已经判断有token所以也会执行业务逻辑,这样还是不能保证幂等性。其实现方法可以使用分布式锁将查询token和删除token两步锁住。

分布式锁理解图:

 3)使用Post/Redirect/Get模式

这种方式就是提交后执行页面重定向,PRG(Post-Redirect-Get)模式。
也就是说用户提交表单后,去执行一个客户端的重定向,重定向到提交成功的信息页面。这样就算刷新也是刷新提交成功的信息页面,能够避免页面刷新导致的重复提交;也不会出现浏览器表单重复提交的警告,也能消除按浏览器前进后退按钮导致的问题。

4)使用数据库乐观锁

使用版本号控制,在业务表中增加一个version字段,记录每次更新的版本

//1.查询出要下单商品的信息        
select stockCount, version from good where id=1;  

        

//2.修改要下单商品的库存数量
update good set stockCount=stockCount-1, version = version+1 where id=1, version=version;

id为1,version为3,stockCount为5。第一个请求拿着id为1,version为3的商品信息去更新库存为4,版本号为4;其他同时的请求过来拿着id为1,version为3更新失败。

这样就算有多次请求同时过来,也只有一个请求会执行成功,保证了顺序执行请求。

其实还有好多方案,这个到时用到再学习。

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

躺着听Jay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值