或许到这里基于单机Redis环境的分布式就介绍完了。但是使用java的同学有没有发现一个锁的重要特性
那就是锁的重入,那么分布式锁的重入该如何实现呢?这里就留一个坑了
4 集群Redis的分布式锁在Redis的分布式环境中,Redis 的作者提供了RedLock 的算法来实现一个分布式锁。
4.1 加锁RedLock算法加锁步骤如下
获取当前Unix时间,以毫秒为单位。
依次尝试从N个实例,使用相同的key和随机值获取锁。在步骤2,当向Redis设置锁时,客户端应该设置一个网络连接和响应超时时间,这个超时时间应该小于锁的失效时间。例如你的锁自动失效时间为10秒,则超时时间应该在5-50毫秒之间。这样可以避免服务器端Redis已经挂掉的情况下,客户端还在死死地等待响应结果。如果服务器端没有在规定时间内响应,客户端应该尽快尝试另外一个Redis实例。
客户端使用当前时间减去开始获取锁时间(步骤1记录的时间)就得到获取锁使用的时间。当且仅当从大多数(这里是3个节点)的Redis节点都取到锁,并且使用的时间小于锁失效时间时,锁才算获取成功。
如果取到了锁,key的真正有效时间等于有效时间减去获取锁所使用的时间(步骤3计算的结果)。
如果因为某些原因,获取锁失败(没有在至少N/2+1个Redis实例取到锁或者取锁时间已经超过了有效时间),客户端应该在所有的Redis实例上进行解锁(即便某些Redis实例根本就没有加锁成功)。
5.2 解锁向所有的Redis实例发送释放锁命令即可,不用关心之前有没有从Redis实例成功获取到锁.
关于RedLock算法,还有一个小插曲,就是Martin Kleppmann 和 RedLock 作者 antirez的对RedLock算法的互怼。 官网原话如下
Martin Kleppmann analyzed Redlock here. I disagree with the analysis and posted my reply to his analysis here.
更多关于RedLock算法这里就不在说明,有兴趣的可以到官网阅读相关文章。
5 总结这篇文章讲述了一个基于Redis的分布式锁的编写过程及解决问题的思路,但是本篇文章实现的分布式锁并不适合用于生产环境。java环境有 Redisson 可用于生产环境,但是分布式锁还是Zookeeper会比较好一些(可以看Martin Kleppmann 和 RedLock的分析)。
Martin Kleppmann对RedLock的分析: