25min
以下涉及到的都是一人操作时候,多次点击造成的并发,对幂等性问题的影响。
大多适用场景,都是单表。没有兼顾数据库分库分表分区场景。
幂等性定义:无论对某一个资源操作了多少次,其影响都应该是相同的。换句话说,在接口重复调用的情况下,对系统产生的影响是一样的,但是返回值允许不同,如查询。
1)幂等性的概念
幂等性不仅仅只是一次或者多次操作对资源没有产生影响,也包含第一次操作产生影响后,以后多次操作不会再产生影响。并且幂等性关注的是 是否对资源产生影响,而不关注结果。
2)接口幂等性方案-----------------------------
在增删改查中,一般是增会产生幂等性问题,需要去规避。
前端,防止幂等性的做法总结:
防止重复提交,加遮罩;防止刷新页面或者前进后退导致页面重复提交,利用重定向成功后转向一个成功提交页面
后端方案:token机制
给客户端一个token,两种细节方案:1.redis存token,客户操作时候验证redis是否有token,有的话操作业务然后删除redis中的token,但是对两个操作需要加锁,防止错误;2.借助redis单线程和incr的原子性,这次redis中存储以token为key的键值对,对值自增,第一次获取token,值是1,第二次操作业务的时候,如果返回值只能是2的时候,允许操作业务。另外一种有问题的场景需要避免,是可能执行业务的时候超时或者异常,于是采用的是先删除token,再执行业务,业务有问题,客户重新去获取token执行新的操作。
缺点:多次交互,执行一次业务操作,需要多次交互,资源浪费大;单线程并发量有限,但是能满足大多数性能要求了
思考:这种幂等性的代码,遍布在每个功能中,导致代码重复度很高,有没有一劳永逸的办法?
55min
怎么不用token,也能达成效果,降低浪费?
1h03min
提取公共的业务:拦截器,认证token,并且删除token
3)服务幂等性方案-----------------------------
1.防重表,(多建立一张表,对一个字段或者多字段建立唯一索引)只适用于数据新增的情况,缺点:不适用于分库分表的场景
2.select+insert操作,mysql乐观锁应对比较简单的方式,(搜索到了,提示重复;搜索不到,进行业务操作;数据库必须设置唯一索引,利用了乐观锁思想,查询默认没有被修改,修改时候利用数据库表的行锁机制)缺点:只适合并发量不高的操作。
注意:更多的是防止个人调用的时候多次点击,
注意: 数据库必须设置唯一索引,只适用于单表;分库分表分区后不再适用。
锁失效:方法上syconizeded 和@transtaction 一起使用出现失效
transaction操作的是方法对象的代理对象。锁 锁住的是方法本身。导致两个操作的不是同一个对象
解决办法:
乐观锁的定义
重点:读的时候,认为无人修改;改的的时候,锁住表
悲观锁:读的时候,也会锁住表。
乐观锁的使用,适用于修改场景,如库存减少的并发场景
版本号控制方式也只使用修改,不好使用添加,因为添加的版本每次是0;版本号不需要自增,版本号达不到控制的效果了。
高并发下的减库存(update)出现幂等性问题,数据不一致,怎么解决?
syconnizsed 加在方法上,不行,会失效。原因:当前synchonized会和方法上的注解Tranaction有不统一, Transaction会有代理类,代理对象,而synchronized锁定的是当前方法对象,所以两个操作了不同的对象,synchronized失效.
解决方法:
1.表字段加version。前端传递过来参数version是确定的,比如0,事务执行完毕以后version变成1,并发执行的的请求带的是0,在dao层,update table where version =#{version}都不符合了。优点缺点:控制了多并发情况下只能有一个成功的场景,拍卖;减库存,库存量不止一个的情况。
2.减库存,更合适的方案,不发生超卖就是合适的:在dao层,update table set amount = amount - #{num} where amount - #{num}>=0
总结:乐观锁保证并发问题,只适用于修改场景,不适用于新增场景
数据库表 有行锁,多个修改,默认会排队;
不使用版本号,直接修改数据库数据也是可以的。
聚簇索引 和非聚簇索引的的区别?意义?
乐观锁控制服务间的幂等性
2h19min
feign重试问题,导致重复下单 在减库存问题中该怎么解决??
3.zookeeper
----
幂等性操作:接口重复调用的情况下,对系统产生的影响是一样的,但是返回值允许不同。
通过zookeeper实现幂等性。怎么实现?