zoukankan      html  css  js  c++  java
  • redis分布式锁

    redis 分布式锁

    分布式锁的安全和活性保证:

    1.安全性:相互排斥,在任何时刻里只有一个客户端可以获取锁.

    2.活性A:无死锁,即使锁定资源的客户端崩溃或者被隔离,其他也总可以获得锁.

    3.活性B:容错,只要大部分的redis节点是运行的,客户端就可以获得及释放锁.

    为什么基于failover的实现是不够的

    1.客户端A在master获取了锁,

    2.master在吧key传输给slave之前崩溃了.

    3.slave晋升为master.

    4.B获取了A已经持有的锁.违反安全性

    单实例的正确实现

    获取锁的指令SET resource_name my_random_value NX PX 30000

    只有在key 不存在的时候(NX)设置值,30000ms的过期时间.key设置为'myrandomvalue'.这个值必须是所有客户端和锁请求之间是唯一的.random value是用来安全的释放锁.使用一个脚本告诉redis:只有在key存在的时候,而且key下的value必须和预期的一样.如下lua脚本做的一样.:

    if redis.call("get",KEYS[1]) == ARGV[1] then
        return redis.call("del",KEYS[1])
    else
        return 0
    end
    

    这可以避免删除另一个客户端创造的锁.一个客户端获得锁,在某些操作中花费的时间长于锁有效时间,之后再移除锁,这是锁已经被其他客户端获取了.直接使用del是不安全的,因为可能删除别的客户端持有的锁.所以上面的脚本保证锁只会被持有它的客户端移除.

    redlock算法

    使用分布式版本的算法,我们假定我们有N个redis的master,它们互相独立,我们已经描述了在单实例模式下安全地获取和释放锁.我们使用这种算法在单个节点获取和释放锁.在我们的例子里设置N=5,这样需要运行5个redis master在不同的电脑或者虚拟机上,来保证它们的失败不会相互影响.

    获取锁的操作步骤:

    1.获取当前的时间戳.

    2.依次获取N个实例的锁,使用相同的key和random value.在第2步.设置每个实例的锁,单个实例的过期时间要小于总的锁自动释放时间.比如总的自动释放时间是10s.,过期时间应该少5~50ms.这样可以防止客户端长时间阻塞,试图与已经关闭的redis节点通话.如果一个实例不可用,我们应该链接下一个实例ASAP.

    3.客户端计算获取锁需要花多少时间,通过减去步骤1里的时间戳.只有client可以获取大多数的实例(至少3),然后总的花费时间少于锁的有效时间,锁被认为是获取的.

    4.如果锁被获取了.它的有效时间是初始化有效时间减去已花掉的时间.如步骤3里计算的那样.

    5.如果客户端获取锁失败(也包括没锁住N/2+1个实例或者有效时间失效).它就会释放所有的实例(甚至包括它没锁住的).

    java的redlock实现

  • 相关阅读:
    3.Appium运行时出现:Original error: Android devices must be of API level 17 or higher. Please change your device to Selendroid or upgrade Android on your device
    3.Python连接数据库PyMySQL
    2.Python输入pip命令出现Unknown or unsupported command 'install'问题解决
    2.Linux下安装Jenkins
    5.JMeter测试mysql数据库
    Android 4学习(7):用户界面
    Android 4学习(6):概述
    Android 4学习(5):概述
    Android 4学习(4):概述
    Android 4学习(3):概述
  • 原文地址:https://www.cnblogs.com/saias/p/9250647.html
Copyright © 2011-2022 走看看