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实现

  • 相关阅读:
    computed的用法
    地址列表展开功能/默认选中功能
    简易编辑器
    用vue做todolist
    用vue做的购物车结算的功能
    如果数据返回没有那个字段,怎么加上去?
    vue中全局filter和局部filter怎么用?
    editorconfig
    eslint 配置
    react typescript 单元测试
  • 原文地址:https://www.cnblogs.com/saias/p/9250647.html
Copyright © 2011-2022 走看看