三、注意点
1. 首先,这个锁必须要设置一个过期时间。否则的话,当一个客户端获取锁成功之后,假如它崩溃了,或者由于发生了网络分割导致它再也无法和Redis节点通信了,那么它就会一直持有这个锁,而其它客户端永远无法获得这个锁了。
2. 第二,第一步获取锁的操作,把它实现成了两个Redis命令,SETNX+EXPIRE。虽然这两个命令和前面描述中的一个SET命令执行效果相同,但却不是原子的。如果客户端在执行完SETNX后崩溃了,那么就没有机会执行EXPIRE了,导致它一直持有这个锁。
3. 第三,设置一个随机字符串randomVal是很有必要的,它保证了一个客户端释放的锁必须是自己持有的那个锁。(最好是唯一性UUID)
4. 第四,释放锁的操作必须使用Lua脚本来实现。释放锁其实包含三步操作:GET、判断和DEL,用Lua脚本来实现能保证这三步的原子性。(获取锁也可通过Redis+Lua实现)
四、思考
还有一个问题是由failover引起的,基于单Redis节点的分布式锁无法解决的。假如Redis节点宕机了,那么所有客户端就都无法获得锁了,服务变得不可用。为了提高可用性,我们可以给这个Redis节点挂一个Slave,当Master节点不可用的时候,系统自动切到Slave上(failover)。但由于Redis的主从复制(replication)是异步的,这可能导致在failover过程中丧失锁的安全性。针对这个问题,可以参考一下Redlock的算法(https://redis.io/topics/distlock)。
作者:ggmack
链接:https://www.jianshu.com/p/bc8dd3c0db22
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。