1、什么是幂等性:
HTTP/1.1中对幂等性的定义是:一次和多次请求某一资源对于资源本身应该具有同样的结果(网络超时等问题除外)。也就是说,其任意多次执行对资源本身所产生的影响均与一次执行的影响相同。
就是用户对于同一接口发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用
即同一个接口,多次发起同一个请求,必须保证操作只能执行一次。
因此在许多业务场景中,需要保证客户端的重复提交和服务端的多次重试,而资源只会产生一份最终结果。幂等机制的核心,就是保证资源唯一性。
如:订单接口,不能创建多个订单
支付接口,重复支付同一笔订单只能扣一次钱
表单重复提交,只能成功一次(保存一条记录)
回调接口,如果出现多次回调,则要保证只处理一次,并返回处理成功
2、解决方案
1、唯一索引(防止新增脏数据)
唯一索引或唯一组合索引来防止新增数据存在脏数据
当表存在唯一索引,并发时新增报错,说明记录已经存在了,返回成功即可。
2、token机制+redis(防止页面重复提交)
由于重复点击或者网络重发,或者nginx重发等情况会导致数据被重复提交
具体实现:
1)提供一个生成全局唯一随机数token的接口,在客户端获取token的时候,将token存入redis中。
客户端请求业务接口时,将获取的token放在header或者作为请求参数请求接口。
每次调用,校验token在redis中是否存在,如果存在,业务处理成功后,从redis中删除此token。如果不存在,说明重复调用,返回请勿重复操作即可。
2)同样提供一个生成全局唯一随机数token的接口,客户端请求业务接口时,将获取的token放在header或者作为请求参数请求接口。
第一次调用,业务处理成功后,将随机数作为key,操作结果作为value,存入redis,同时设置过期时长。第二次调用,查询redis,如果key存在,则证明是重复提交,直接返回错误。
3、悲观锁,获取数据的时候加锁获取
4、乐观锁,在更新数据的时候锁表,其他时间不锁表。可通过version版本号实现
5、分布式锁,redis或者zookeeper分布式锁。
6、先查询,后插入