美文网首页
分布式锁之Redis 分布式锁

分布式锁之Redis 分布式锁

作者: BestFei | 来源:发表于2020-04-05 14:22 被阅读0次

    使用 Redis 分布式锁,一般用 Redisson 框架就好了,非常的简便易用。

    一、Redisson 实现 Redis 分布式锁的底层原理

    1、加锁机制

    如果客户端A要加锁,面对的是一个 Redis Cluster 集群,首先会根据 Hash 节点选择一台机器。
    紧接着,就会发送一段 Lua 脚本到 Redis 上。Lua 脚本中封装了一大坨复杂的业务逻辑,这些发送给 Redis 保证这段复杂业务逻辑执行的原子性。
    加锁的过程是这样的:
    根据Key加锁,如要加锁的 Key 不存在的话,则进行加锁,一般设置默认生存时间30 秒,和设置加锁的客户端的 ID。
    例如:客户端ID:870621bf-i520-8888-87bf-881013jm2222:1,要给锁 Key 为 myKeyName的加锁,加锁成功以后会看到这样一个Hash 数据结构

    myKeyName:
    {
      "870621bf-i520-8888-87bf-881013jm2222:1" : 1
    }
    
    2、锁互斥机制

    在客户端 A 加锁成功以后,客户端 B 来尝试加锁,执行了同样的一段 Lua 脚本,
    此时锁 Key 已经存在了,且锁 Key对应的客户端 ID并不是客户端 B ,
    客户端 B 会获取到这个锁的剩余生存时间,此时客户端 B 会进入一个循环,不停的尝试加锁。

    3、watch dog 自动延期机制

    客户端 A 加锁的锁 Key 默认生存时间才 30 秒,如果超过了 30 秒,客户端 A 还没有执行完任务,还想继续持有这把锁,怎么办呢?不用担心,只要客户端 A 一旦加锁成功,就会启动一个 watch dog 看门狗,他是一个后台线程,会每隔 10 秒检查一下,如果客户端 A 还持有锁 Key,那么就会不断的延长锁 Key 的生存时间。

    4、可重入加锁机制

    那如果客户端 A 已经持有了这把锁了,结果可重入的加锁会怎么样呢?
    对于同一个锁 Key的客户端 ID,会增加对客户端 A 的加锁次数,累加 1。
    此时Hash 数据结构会变成

    myKeyName:
    {
      "870621bf-i520-8888-87bf-881013jm2222:1" : 2
    }
    
    5、释放锁机制

    每次任务完成后执行释放分布式锁,Hash 数据结构中的那个加锁次数减 1。
    如果发现加锁次数是 0 了,说明这个客户端已经不再持有锁了,此时就会从 Redis 里删除这个 Key。
    此时轮询等待的客户端 B 就可以尝试完成加锁了。这就是所谓的分布式锁的开源 Redisson 框架的实现机制。

    二、Redis 分布式锁的缺点

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

    相关文章

      网友评论

          本文标题:分布式锁之Redis 分布式锁

          本文链接:https://www.haomeiwen.com/subject/giduphtx.html