分布式锁的实现
满足的条件
互斥性
不会发生死锁
1
| 即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。
|
解铃还须系铃人
1
| 加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了。
|
原子性
步骤
一、多个客户端申请获取锁
二、获取成功
1
| 即执行setnx语句成功后的客户端,其他客户端等待重试
|
三、执行业务逻辑
四、释放锁
总结
问题一
解决方案
问题二
1 2 3 4 5 6 7 8
| 在解决问题一后,可能存在释放了其他客户端上的锁,现象如下:
1. index1业务逻辑没执行完,3秒后锁被自动释放。 2. index2获取到锁,执行业务逻辑,3秒后锁被自动释放。 3. index3获取到锁,执行业务逻辑 4. index1业务逻辑执行完成,开始调用del释放锁,这时释放的是index3的锁,导致index3的业务只执行1s就被别人释放。
最终等于没锁的情况。
|
解决方案
1 2 3
| setnx获取锁时,设置一个指定的唯一值(例如:uuid);释放前获取这个值,判断是否自己的锁
解决了上锁和释放锁是同一个客户端
|
问题三
1 2 3
| 在解决问题二后,删除操作缺乏原子性,现象如下:
可能存在有一个客户端刚好执行到删除del语句,而且已经完成了uuid的判断,但已经过期,此时第二个客户端开始上锁,可恰好第一个客户端开始执行del语句,导致第二个客户端的lock被删除
|
解决方案
与Zookeeper分布式锁的差异
1 2
| Redis性能高,但是需要多重优化,而且客户端需要不断去尝试获取锁,比较耗性能 Zookeeper可靠性强,不需要不断主动尝试获取锁,只需要负责监听前一个节点即可,性能开销较小
|