业务中如何保证幂等性?

接口幂等性:用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。通俗点就是不会对数据库产生副作用。

  1. 在支付业务中,一定要保证接口的幂等性。例如如果用户发起了一次支付,后台完成了支付的逻辑,以及订单状态的修改,但由于网络波动,用户没收到后台返回过来支付成功的请求,使得用户感觉没有付款成功,而又进行了一次付款,导致一个订单扣了两次款,流水也生成了两条这是万万不可的!
    在这里插入图片描述

  2. 还有种情况,假如用户单身20年,手速到达了一个巅峰,在确认支付的时候快速地点击了两次,虽然前端应该可以控制按钮不能重复点击,但也可以通过分析接口,用一些postman这类的工具实现瞬间多次请求接口,所以多次请求接口时,不做一些预防处理,也会导致一个订单会被请求多次。

那如何保持幂等性呢?
对于第一种情况,常见的两种实现方案: 1. 通过代码逻辑判断实现 2. 使用token机制实现。
我们知道,支付肯定是对用户的某一个订单进行支付,在支付前肯定生成了一个订单,而订单肯定是唯一性的,可能是订单表的主键,也可能是某一个通过uuid生成的字段。如果用户在第一次对订单进行支付请求,后台完成了支付操作,订单的状态也update为付款成功的状态,但操作成功的信息未返回到前端,用户在进行第二次进行支付请求的时候,也是对同一个订单进行支付请求,此时这笔订单状态是付款成功了,所以在每一次发起支付逻辑前要对订单的状态进行判断,如果状态是付款成功了就不需要去调第三方渠道的支付请求了。
至于基于token机制,看到其他博客都是些的token是一次有效,但项目中是使用token是放在header里的,每次请求都会校验token数据里的用户名、权限等内容,需要每次请求都要携带token,所以与这里的token一次有效有出入,所以选择了使用redis锁来防止订单的重复提交。

对于那些手速快的,或者频繁调用接口的,就可以使用加锁的方式来让请求在某一段时间内只会有一个请求执行,因为每一次请求都会创建新的线程,不管是不是同一个用户,用一个浏览器,所以使用redis锁,还是使用mysql建立一张锁表,都可以达到效果。
如果使用本地缓存锁,就算是同一个用户,同一个手机进行操作,线程还是不同的,所以不会有重入的情况发生,但是就无法区分操作是同一用户还是多个用户进行操作了,如果锁的部分逻辑复杂,执行时间较长,就意味着其他线程就获取不到锁,从而导致性能降低,而且使用本地缓存锁,还需要考虑生产环境是否是分布式部署,如果是就需要使用分布式锁来同步本地缓存锁的数据,所以本地缓存锁并不是一个解决方案,而且ReentrantLock无法设置加锁时间,只能设置尝试获取锁的时间:tryLock(long timeout,TimeUnit unit)。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值