• Redis面试题(四)



    前言

    1. 锁互斥机制
    2. watch dog 自动延期机制
    3. 可重入加锁机制
    4. 释放锁机制
    5. 上述 Redis 分布式锁的缺点
    6. 使用过 Redis 分布式锁么,它是怎么实现的?

    `

    一、锁互斥机制

    那么在这个时候,如果客户端 2 来尝试加锁,执行了同样的一段 lua 脚本,会咋样呢?很简单,第一个 if 判断会执行“exists myLock”,发现 myLock 这个锁 key 已经存在了。接着第二个 if 判断,判断一下,myLock 锁 key 的 hash 数据结构中,是否包含客户端 2 的 ID,但是明显不是的,因为那里包含的是客户端 1 的 ID。
    所以,客户端 2 会获取到 pttl myLock 返回的一个数字,这个数字代表了 myLock 这个锁 key的 剩余生存时间。比如还剩 15000 毫秒的生存时间。此时客户端 2 会进入一个 while 循环,不停的尝试加锁。


    二、watch dog 自动延期机制

    客户端 1 加锁的锁 key 默认生存时间才 30 秒,如果超过了 30 秒,客户端 1 还想一直持有这把锁,怎么办呢?
    简单!只要客户端 1 一旦加锁成功,就会启动一个 watch dog 看门狗, 他是一个后台线程,会每隔 10 秒检查一下,如果客户端 1 还持有锁 key,那么就会不断的延长锁 key 的生存时间。


    三、 可重入加锁机制

    那如果客户端 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,就对应着加锁的次数


    四、释放锁机制

    如果执行 lock.unlock(),就可以释放分布式锁,此时的业务逻辑也是非常简单的。其实说白了,就是每次都对 myLock 数据结构中的那个加锁次数减 1。如果发现加锁次数是 0 了,说明这个客户端已经不再持有锁了,此时就会用:“del myLock” 命令,从 redis 里删除这个 key。
    然后呢,另外的客户端 2 就可以尝试完成加锁了。这就是所谓的 分布式锁的开源 Redisson 框架的实现机制。
    一般我们在生产系统中,可以用 Redisson 框架提供的这个类库来基于 redis 进行分布式锁的加锁与释放锁。

    五、 上述 Redis 分布式锁的缺点

    其实上面那种方案最大的问题,就是如果你对某个 redis master 实例,写入了 myLock 这种锁key 的 value,此时会异步复制给对应的 master slave 实例。但是这个过程中一旦发生 redis master 宕机,主备切换,redis slave 变为了 redis master。
    接着就会导致,客户端 2 来尝试加锁的时候,在新的 redis master 上完成了加锁,而客户端 1
    也以为自己成功加了锁。此时就会导致多个客户端对一个分布式锁完成了加锁。这时系统在业务语义上一定会出现问题, 导致各种脏数据的产生。
    所以这个就是 redis cluster,或者是 redis master-slave 架构的主从异步复制导致的 redis 分布式锁的最大缺陷:在 在 redis master 实例宕机的时候,可能导致多个客户端同时完成加锁。


    六、使用过 Redis 分布式锁么,它是怎么实现的?

    先拿 setnx 来争抢锁,抢到之后,再用 expire 给锁加一个过期时间防止锁忘记了释放。
    如果在 setnx 之后执行 expire 之前进程意外 crash 或者要重启维护了,那会怎么样?
    set 指令有非常复杂的参数,这个应该是可以同时把 setnx 和 expire 合成一条指令来用的!


    总结

    1. 锁互斥机制
    2. watch dog 自动延期机制
    3. 可重入加锁机制
    4. 释放锁机制
    5. 上述 Redis 分布式锁的缺点
    6. 使用过 Redis 分布式锁么,它是怎么实现的?
  • 相关阅读:
    C++面向对象OOP-构造函数
    Unity SRP 管线【第二讲:Draw Call】
    计算机网络
    矩阵点乘multiply()函数和矩阵乘法dot()函数
    也谈一下 30+ 程序员的出路
    C++ 宏定义中的##
    跨站脚本攻击xss攻击
    单元测试-学习笔记
    【国科大——矩阵分析与应用】使用高斯消元法,测试二元一次方程系数产生的误差
    Vue Vuex模块化编码
  • 原文地址:https://blog.csdn.net/weixin_47924016/article/details/133085841