Redis基于setnx的分布式锁,存在以下的问题
1.锁不可重入(uuid+线程id),2.不可重试(自旋while),3.超时释放(watchdog),4.主从一致性问题(red lock)
单机模式下使用全局锁(synchronized),当多线程过来的时候,会产生互斥,只有一个线程能获取到锁,其他线程陷入等待
通过setNX去存储一个值的时候,他会通过这个key(键)中判断value是否有值,如果没有值,就存入返回true(加锁成功),否则返回false(失败),通过此特性实现分布式锁
1.1超时释放:
综上所述,存入时尽量加个过期时间,不然获取锁成功后,服务器突然宕机,导致死锁.其他的服务器请求依然处于阻塞状态.因为上锁时,发现key(键)中一直会有值(锁未释放掉),所以无法成功上锁,宕机的服务器一直持有锁,形成死锁.加上过期时间,时间到了自动释放锁
解决方案:看门狗机制watchdog(30秒),添加一个子线程,每隔10秒去检查当前业务是否执行完,没有执行完,就将过期时间重置(30秒)
1.2锁不可重入:
当(线程a)业务执行时间大于锁过期时间,业务还没有执行完,这个锁他会自动释放,导致其他线程(线程b)进入,线程a释放了线程b的锁,从而导致误删(线程)锁
解决方案:给锁增加一个唯一id(uuid)拼接(+线程id),保证每一把锁绑定自己的线程,从而不会释放其他锁
1.3不可重试:
如果没有获取锁,会产生自旋,不停的获取锁(while),直至超时
(redis采用的ap模式,保证高可用,高性能,不能保证高一致)
1.4主从一致性问题:
redis使用了主从集群,master设置key(键)获取了锁,还没来得及同步backup(slave),master宕机了,backup没有获取到锁,依然会产生线程安全问题,默认是master的key(键)获取到锁,直接响应获取成功,(此时宕机)此时就无法同步给backup.从而导致线程安全问题.
解决方案:(red lock)他主要是针对redis中的所有节点进行同步,保证master和backup同步完成后,才会响应获取锁成功,就能保证了强一致性.
本人小白一名,如有偏差欢迎指点!