笔记内容
redis实现分布式锁
以上代码会出现并发超卖问题,所以加同步锁简单解决
这样在集群架构环境下(多台服务器)环境下会出现超卖问题
集群环境下(两个jvm)进行对同一个redis操作,a将库存改为277后,b某时刻又将库存改为278,a又获取到288并改为277,所以就出现超卖问题
用setnx解决问题
setnx是执行单线程进行,且要是对一个key进行setnx操作,后面在对这个key是无效的
问题:
拿到锁后的线程执行业务在中途发生异常,便不会执行释放锁的操作,死锁
放在try-catch-finaly中
问题2:执行过程中出现宕机问题。finally中的代码也执行不了
解决:加入锁失效时间(分布式锁超时时间)
两行代码分开写也会出现在执行前main一行代码后出现宕机,便不会释放锁,于是将两行代码合并成一行代码(另外一个不同参数个数的方法)
以上就差不多解决了,但是在高并发环境中,也会出现问题
比如:在高并发场景的时候请求一个接口需要的时间较长(需要耗时15秒),那么在执行业务代码的时候还没执行到finally,就超过15秒,锁就失效了,第二条线程就会获得锁,但第一条线程会继续往下执行,导致把第二条线程的锁给释放。后面类似情况,出现大面积所失效问题。
问题的根本点:a线程假的锁被b线程给释放掉
给锁加个身份表示:用uuid产生
讨论:为什么不使用线程id作为锁的身份标识
答:在分布式环境下,每台服务器上可能有相同的线程id
上面执行finally是也会出现极端问题:
当一线程执行到if语句代码块中,还没释放锁,这个时候锁超时了,另外一个线程加锁成功,这个时候继续往下执行,便会把另外一个线程的锁给释放了,出现上面类似问题。
解决方法:锁续命 watch dog
在主线程之下开一个分线程来判断主线程有没有执行完成,要是没执行完成就会将超时时间重置,这样只要主线程没有执行完,锁就永远不会失效。
具体实现:Redisson
引入依赖- redisson
初始化redisson客户端
注入到容器
获锁,加锁 解锁
更改以上加锁方式,用redisson方式加锁
替换掉这个
为