幂等性问题以及解决方案
作者:互联网
幂等性问题以及解决方案
目录1、问题
- 说一说什么是幂等?
- 如何去解决幂等性问题?
2、回答
2.1、说一说什么是幂等?
先给予名词上的解释:所谓幂等,其实它是一个数学上的概念。
我们认知的解释:而在计算机编程领域呢,幂等一般是指方法被多次执行的时候所产生的影响和其第一次产生的影响是相同的
为什么会存在:之所以要考虑幂等性问题,是因为在网络通信里存在两种行为可能会导致接口被重复调用
- 不可控因素:用户的重复提交或恶意攻击,导致请求重复
- 为了解决另外的问题所导致的:在分布式架构中,为了避免网络通信导致的数据丢失,在服务之间进行通信的时候,一般都会设计超时重试这样一个机制,而这种机制有可能导致服务端接口被重复调用
所以对于数据变更类的接口(一般情况下查询和删除操作有天然的幂等性),我们要保证接口的幂等性,而其核心思想就是保证这个接口只执行一次,后续再次调用也不能对数据产生任何的影响。
2.2、那么,我们对于这幂等性问题,有什么解决方案呢?
2.2.1、唯一索引
唯一索引:使用数据库唯一约束实现幂等,比如对于数据插入类场景,假如是创建订单,订单id肯定是唯一的,给订单id加上唯一索引,那么我们在多次创建订单时,会触发数据库的唯一约束异常,这样就保证不管是以何种方式落库,数据库的记录都具有唯一性。
2.2.2、Redis命令
Redis命令:使用Redis里面提供的setNX指令,比如对于为了避免MQ重复消费导致多次数据被修改,我们可以在消息到数据时,把这个消息通过setNx写入到Redis中,一旦这个消息被消过,就不会再次消费(过期时间由业务决定)
2.2.3、状态机
状态机:使用状态机来实现幂等,所谓的状态机是指一条数据的完整运行状态的转换流程,比如订单状态,因为他的状态只会向前变更,所以多次修改同一条数据的时候,一旦状态发生变更,那么对这条数据修改造成的影响只发生一次
2.2.4、token
token:数据提交前要向服务的申请token,token放到redis或jvm内存,token需要设置有效时间,一般我们一个请求从request到respond时间是很短的,所以有效时间可以设置短一点;(分布式场景下锁要第三方提供的)
提交到后台校验token,同时删除token,返回执行结果。token特点:一次有效性,用完即删,可以限流执行。
2.2.5、悲观锁
悲观锁:获取数据的时候加锁获取。
select * from t_name where id='xxx' for update;
注意:这边的id字段一定是主键或者唯一索引,不然会导致锁表。悲观锁使用时一般会配合事务一起使用,数据锁定时间可能会很长,根据实际情况选用。 具体详情可以看:大佬链接
2.2.6、乐观锁
乐观锁:乐观锁只是在更新数据那一刻锁表,其他时间不锁表,所以相对于悲观锁,效率更高,适用于多读少写的类型,并发大的情况。
乐观锁的实现方式多种多样,可以通过version或者其他状态条件:
- 通过版本号实现
update t_name set name=#{name},version=version+**1** where version=#{version};
- 通过条件限制
update t_name set avai_amount=avai_amount-#subAmount# where avai_amount-#subAmount# >= 0
使用版本号的方式执行过程如下图:
这边需要注意: 乐观锁的更新操作,如果加上主键或者唯一索引来作为条件, 更新时锁的是行,否则更新时会锁表,性能效率差很多。所以上面两个sql改成下面两个会好很多。
update t_name set name=#name#,version=version+1 where id=#id# and version=#version#;
update t_name set avai_amount=avai_amount-#subAmount# where id=#id# and avai_amount-#subAmount#
参考链接:
https://heapdump.cn/article/3145412
https://zhuanlan.zhihu.com/p/355103045
https://zhuanlan.zhihu.com/p/348316955
标签:name,以及,解决方案,问题,token,version,avai,2.2,id 来源: https://www.cnblogs.com/lishanbiaosMark/p/16321440.html