接口幂等性问题,对于开发人员来说是一个常见的公共问题。这里分享一些我在项目中用到过的一些方法,给有需要的同学们一个参考。
你是否遇到过以下的场景:
- 在填写form页面表单时,如果前端没做loading或者防抖操作,保存按钮时不小心快速点了两次,表中竟然产生了两条重复的数据,只是id不一样。
- 在项目中为了解决接口超时问题,通常会使用重试机制。即第一次请求接口超时了,没有获取到返回结果,为了避免直接返回错误的结果,于是会对该请求重试几次,这样也会产生重复的数据。
- 消息队列在读取消息时,有时会读取到重复消息(各种原因导致,这里不展开),如果处理不好,也会产生重复的数据。
以上举例的这些都是幂等性问题。
接口幂等性是指用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。
这类问题多发于接口的:
- insert操作,这种情况下多次请求,可能会产生重复数据;
- update操作,如果只是单纯的更新数据,比如:
update customer set status = 0 where id = 1
,是没有问题的。但如果如果还有计算,比如:update customer set status = status + 1 where id = 1
,这种情况下多次请求,可能会导致数据错误。
1.新增前先查询是否有(insert前先select)
通常情况下,在保存数据的接口中,我们为了防止产生重复数据,一般会在insert
前,先根据name
或mobile
字段select
一下数据。如果该数据已存在,则执行update
操作,如果不存在,才执行 insert
操作。
此可能是我们平时在防止产生重复数据时,使用最多的方案。但是该方案不适用于并发场景,在并发场景中,要配合其他方案一起使用,否则同样会产生重复数据。
2. 数据库加锁
2-1、使用悲观锁
在支付场景中,比如A的账号余额有1000元,买东西支付100元,正常情况下用户A的余额还有900元。一般情况下,sql是这样的:
update customer set money = money-100 where id=1;
如果同一时间内出现多次相同的请求,可能会导致用户A的余额不对。这种情况,对于研发来说就是严重的生产事故了。
这是主角上场了—