美文网首页
redis 分布式锁

redis 分布式锁

作者: 格林哈 | 来源:发表于2020-09-04 16:18 被阅读0次

    1 实现命令

    
    # 成功返回OK 表示持有锁, 失败返回null 获取锁失败
    # 获取锁(unique_value可以是UUID等)
    SET resource_name unique_value NX PX 3000
        NX 只在键不存在时, 才对键进行设置操作
        PX 将键的过期时间设置为 milliseconds 毫秒
        EX 将键的过期时间设置为 seconds 秒
    
    # f封装到一个命令 释放锁(lua脚本中,一定要比较value,防止误解锁)
    if redis.call("get",KEYS[1]) == ARGV[1] then
        return redis.call("del",KEYS[1])
    else
        return 0
    end
    
    redis.call() 执行命令 ,过程中发生错误时,脚本会停止执行
    redis eval  可以执行脚本, 所有键都应该由 KEYS 数组来传递
    如: eval "return redis.call('set',KEYS[1],'bar')" 1 xxp
    # 在命令的最后,那些不是键名参数的附加参数 arg [arg ...] ,可以在 Lua 中通过全局变量 ARGV 数组访问
    eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
    
    
    • 缺点
      • 只能作用在一个节点,即使通过sentinel 保证高可用,master节点主从切换 可能出现丢失情况
        • master 拿到锁
        • 锁没有同步到slave节点
        • master 故障,发生故障转移,slave节点升级为master节点
        • 导致锁丢失

    2 redis作者Redlock实现

    • 获取锁的算法 假设当前有5个节点
      • 获取当前时间戳,单位毫秒
      • client 按照顺序使用key,value 获取所有redis服务的锁,客户端设置一个网络连接和响应超时时间,这个超时时间要小于锁的失效时间。
        -例如 锁失效 10s,超时时间 5-50ms,比较服务器redis挂掉,客服端等待,应该尽快去访问下个redis实例
      • 当大多数(n/2+1,这里是三个)的redis节点获取到锁,并且 使用的时间小于锁失效时间获取锁成功
        • 使用的时间 = 当前时间-开始获取锁的时间 ,即步骤1获取的时间戳
      • 获取到锁,key真正有效时间 = 有效时间 - 获取锁使用时间
      • 获取锁失败,客户端应该对所有redis实例进行解锁
        • 获取锁失败, 没有n/2+1实例获取到锁,或者锁 有效时间 超过 获取锁的时间
        • 解锁:因为小于3个锁,必须释放,或者影响其他client 获取锁

    参考

    相关文章

      网友评论

          本文标题:redis 分布式锁

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