幂等性问题:
幂等性问题指的是一个接口多次执行的结果应当与一次执行的结果相同(即重复操作不会对数据准确性造成影响)。 在数据不变的情况下,查询和删除操作天然具备幂等性,而新增和修改操作默认情况下不能保证幂等。
幂等性解决方案:
在高并发场景的架构里,幂等性是必须得保证的。比如说支付功能,用户发起支付,如果后台没有做幂等校验,刚好用户手抖多点了几下,于是后台就可能多次受到同一个订单请求,不做幂等很容 易就让用户重复支付了,这样用户是肯定不能忍的。
解决方案:
-
查询和删除不在幂等讨论范围,查询肯定没有幂等的说,删除:第一次删除成功后,后面来删 除直接返回0,也是返回成功。
-
建唯一索引:唯一索引或唯一组合索引来防止新增数据存在脏数据 (当表存在唯一索引,并发
时新增异常时,再查询一次就可以了,数据应该已经存在了,返回结果即可)。 -
token机制:由于重复点击或者网络重发,或者nginx重发等情况会导致数据被重复提交。前端
在数据提交前要向后端服务的申请token,token放到 Redis 或 JVM 内存,token有效时间。提交后
后台校验token,同时删除token,生成新的token返回。redis要用删除操作来判断token,删除成
功代表token校验通过,如果用select+delete来校验token,存在并发问题,不建议使用。 -
悲观锁:悲观锁使用时一般伴随事务一起使用,数据锁定时间可能会很长,根据实际情况选用(另外还要考
虑id是否为主键,如果id不是主键或者不是 InnoDB 存储引擎,那么就会出现锁全表)。select id ,name from table_# where id='##' for update;
-
乐观锁:给数据库表增加一个version字段,可以通过这个字段来判断是否已经被修改了
update table_xxx set name=#name#,version=version+1 where version=#version#
-
分布式锁:比如 Redis 、 Zookeeper 的分布式锁。单号为key,然后给Key设置有效期(防止支
付失败后,锁一直不释放),来一个请求使用订单号生成一把锁,业务代码执行完成后再释放锁。 -
保底方案,先查询是否存在此单,不存在进行支付,存在就直接返回支付结果。