及时行乐|这些Redis面试题是不是让你有很多问号?一文带你吊打面试官( 四 )


28.加锁机制
咱们来看上面那张图 , 现在某个客户端要加锁 。 如果该客户端面对的是一个 redis cluster 集群 , 他首先会根据 hash 节点选择一台机器 。 这里注意 , 仅仅只是选择一台机器!这点很关键!紧接着 , 就会发送一段 lua 脚本到 redis 上 , 那段 lua 脚本如下所示:为啥要用 lua 脚本呢?因为一大坨复杂的业务逻辑 , 可以通过封装在 lua 脚本中发送给 redis , 保证这段复杂业务逻辑执行的原子性 。 那么 , 这段 lua 脚本是什么意思呢?这里 KEYS[1]代表的是你加锁的那个 key , 比如说:RLock lock = redisson.getLock("myLock");这里你自己设置了加锁的那个锁 key 就是“myLock” 。 ARGV[1]代表的就是锁 key 的默认生存时间 , 默认 30 秒 。 ARGV[2]代表的是加锁的客户端的 ID , 类似于下面这样:8743c9c0-0795-4907-87fd-6c719a6b4586:1给大家解释一下 , 第一段 if 判断语句 , 就是用“exists myLock”命令判断一下 , 如果你要加锁的那个锁 key 不存在的话 , 你就进行加锁 。 如何加锁呢?很简单 , 用下面的命令:hset myLock8743c9c0-0795-4907-87fd-6c719a6b4586:1 1 , 通过这个命令设置一个 hash 数据结构 , 这行命令执行后 , 会出现一个类似下面的数据结构:
上述就代表“8743c9c0-0795-4907-87fd-6c719a6b4586:1”这个客户端对“myLock”这个说 key 完成了加锁 。 接着会执行“pexpire myLock 30000”命令 , 设置 myLock 这个说 key 的生存时间是 30 秒 。 好了 , 到此为止 , ok , 加锁完成了 。
29.锁互斥机制
那么在这个时候 , 如果客户端 2 来尝试加锁 , 执行了同样的一段 lua 脚本 , 会怎样呢?很简单 , 第一个 if 判断会执行“exists myLock” , 发现 myLock 这个说 key 已经存在了 。 接着第二个 if 判断 , 判断一下 , myLock 锁 key 的 hash 数据结构中 , 是否包含客户端 2 的 ID , 但是明显不是的 , 因为那里包含的是客户端 1 的 ID 。
所以 , 客户端 2 会获取到 pttl myLock 返回的一个数字 , 这个数字代表了 myLock 这个说 key的剩余生存时间 。 比如还剩 15000 毫秒的生存时间 。 此时客户端 2 会进入一个 while 循环 , 不停的尝试加锁 。
30.watch dog 自动延期机制
客户端 1 加锁的锁 key 默认生存时间才 30 秒 , 如果超过了 30 秒 , 客户端 1 还想一直持有这把说 , 怎么办呢?
简单!只要客户端 1 一旦加锁成功 , 就会启动一个 watch dog 看门狗 , 他是一个后台线程 , 会每隔 10 秒检查一下 , 如果客户端 1 还持有锁 key , 那么就会不断的延长锁 key 的生存时间 。
及时行乐|这些Redis面试题是不是让你有很多问号?一文带你吊打面试官
31.可重入加锁机制
那如果客户端 1 都已经持有了这把锁了 , 结果可重入的加锁会怎么样呢?比如下面这种代码:这时我们来分析一下上面那段 lua 脚本 。 第一个 if 判断肯定不成立 , “exists myLock”会显示锁key 已经存在了 。 第二个 if 判断会成立 , 因为 myLock 的 hash 数据结构中包含的那个 ID , 就是客户端 1 的那个 ID , 也就是“8743c9c0-0795-4907-87fd-6c719a6b4586:1”此时就会执行可重入加锁的逻辑 , 他会用:
incrby myLock 8743c9c0-0795-4907-87fd-6c71a6b4586:1 1, 通过这个命令 , 对客户端 1的加锁次数 , 累加 1 。 此时 myLock 数据结构变为下面这样:大家看到了吧 , 那个 myLock 的 hash 数据结构中的那个客户端 ID , 就对应着加锁的次数
32.释放锁机制
如果执行 lock.unlock() , 就可以释放分布式锁 , 此时的业务逻辑也是非常简单的 。 其实说白了 , 就是每次都对 myLock 数据结构中的那个加锁次数减 1 。 如果发现加锁次数是 0 了 , 说明这个客户端已经不再持有锁了 , 此时就会用:“del myLock”命令 , 从 redis 里删除这个 key 。


推荐阅读