本文关于redis代码实现分布式锁的设计思路,每一步解决上一步的问题
关于redis实现分布式
本文实现的分布式锁并不推荐,首先实现麻烦,容易出问题
其次是未获取锁的线程没有被阻塞,而是要进行自旋,此时特别消耗cpu资源
所以推荐使用redisson,也可以考虑使用zookeeper
实现思路
-
代码实现:
-
上述情况,可能会产生死锁
-
这里设置了过期时间,但是存在的问题在于,在进行
if
判断时,该线程挂了,此时已然死锁 -
所有
setNX
和expire
必须要原子操作
-
使用
setNXEX
保证原子性 -
问题在于,线程A业务时间过长,key过期了,业务还在进行操作,此时其他线程B获得锁。当线程A业务执行完,按照流程执行删锁操作,此时删的锁并不是线程A的,而是线程B的。这种情况就是删掉了别人的锁,同时,可能删掉多个人的锁,那么锁的意义也就不复存在了
-
所以需要指定锁的持有者,只有持有者才能释放锁,这里指定key的值为唯一标识,比如iip+端口+线程,比如uuid
- 这样也会产生问题(忽略判空的bug)
- 问题在于:与redis的交互需要时间,查询的时候锁是自己的,然后删除之前,锁失效了,被别人获取了,此时删除的就又是别人的锁了
- 所以还是要保证原子性,删锁的原子性
- 最终使用lua脚本来进行删除锁
总结:加锁保证原子性,删锁也要保证原子性
(本文是尚硅谷视频的学习笔记)