• redis分布式锁的原理


    如果让我们自己想办法利用redis命令来实现分布式锁机制,需要怎么做呢?

    setnx命令是原子的,在key不存在时创建,创建成功返回true,创建不成功返回false。expire命令可以设置过期时间(防止一直不过期导致死锁)。

    但是这两个命令结合在一起使用时,无法保证原子性。有可能expire命令未执行成功时异常退出,导致key没有设置过期时间,从而引发一些错误。

    于是,可以借助lua脚本来将多个redis命令封装在一个原子操作里。

    现在通常的做法是将exists key,hset key field times,expire key 封装在一起构成加锁操作。这里redis数据类型使用hash不使用String的原因是为了多存储一个加锁次数的字段,为了锁可重入准备的。

    因此,通常的基于redis的分布式锁的实现逻辑为:

    1 执行加锁的lua脚本:exists,hset,expire等。若exists返回false,继续向下执行,直到加锁成功,若exists返回true,则跳转第二步。

    2 判断hash的field字段中是否是当前客户端?若否,则返回key的剩余生存时间,继续循环等待;否则重入锁成功,hincrby key field 1,加锁次数+1。

    3 expire生存时间一到,锁会自动释放,key会被删除 del key。

    4 client每次unlock,field对应的value值减1,直到减为0,del key。

    可能存在的问题:

    若redis是主从配置,client1在master上加锁成功,此时master同步到slave尚未完成,master挂掉了,然后其它slave竞争为master,此时slave上不存在key,此时client2就能在新的master上加锁成功,

    这样就导致了同一个lockkey被两个client同时加锁的情况。

    怎么解决这个问题呢?

    有一个red-lock算法,原理是对所有节点都加锁(而不是只对一个结点加锁),多数通过则成功加锁,否则失败!

    应对你提出的场景就是:第一个请求加锁,多数节点通过加锁成功,各节点保存加锁成功信息;

    这时主节点挂掉,第二个请求来了,请求加锁,多数节点认为锁已经存在不同意加锁,所以加锁失败,只有等待key失效再次加锁。

  • 相关阅读:
    win10系统磁盘占用率高的解决方法,占用100%的问题
    码率/比特率定义
    风好大,我好冷
    风好大,我好冷——团队作品
    风好大,我好冷——团队介绍
    风好大,我好冷——个人分工理解
    风好大,我好冷——团队风采
    命令行作业
    面向对象程序设计作业三
    作业二
  • 原文地址:https://www.cnblogs.com/mydesky2012/p/14924409.html
Copyright © 2020-2023  润新知