分布式锁

  1. 加锁步骤
    1)查看key是否存在
    2)如果不存在,则设置key  值为当前的threadId + 当前服务器的标识ID    和 锁次数      并设置超时时间
    3)已经存在,查询值是否是当前的线程Id,如果是只  增加锁次数
    2)已经存在,但是并非当前线程锁定的,则ppl查询其超时时间并返回剩余时间

     

    if (redis.call('exists', KEYS[1])==0) then
        redis.call('hset', KEYS[1], ARGV[2], 1);
        redis.call('pexpire', KEYS[1], ARGV[2]);
        return nil;
    end;
    if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then
        redis.call('hincrby', KEYS[1], ARGV[2], 1);
        redis.call('pexpire', KEYS[1], ARGV[2]);
        return nil;
    end;
    return redis.call('pttl', KEYS[1]);
        

     

  2.  

    解锁步骤

    1) 查询锁是否存在
    2)不存在则 通知其他线程锁已解锁
    3)查询存在,并比较是否是当前线程上的锁
       不是当前线程,则返回
       是当前线程,则将锁次数减一。如果已经是零,则通知其他线程已解锁
       是当前线程 如果次数还没有到零,则继续续超时时间

    if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) then
        return nil;
    end;
    local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1);
    if (counter > 0) then
        redis.call('pexpire', KEYS[1], ARGV[2]);
        return nil;
    else
        redis.call('del', KEYS[1]);
        redis.call('publish', KEYS[2], ARGV[1]);
        return 1;
    end;
    return nil;
    
    备注:KEY1 :  锁的key
         KEY2 :  通知的channel名称
         ARGV1:  通知的值
         ARGV2:  超时时长
         ARGV3:  当前线程标识

     

  3.  

     强制解锁,这个是不管锁的线程是否是当前线程。如果锁存在,直接解锁

  4. 锁的续期,查询锁的线程是当前线程,则进行锁的超时时长延迟

    没隔internalLockLeaseTime / 3时长进行续期
    internalLockLeaseTime 代表锁超时时长

     

  5. redission分布式锁的问题以及解决方案
    1、如果客户端在主redis获取锁成功之后,主redis挂了 数据还没有同步到从redis。其他客户端就可以在从
    redis获取相同的锁
       解决办法:通过redLock    采用多个redis实例,多数实例获取成功之后,才算成功
    
    2、如果有5个redis节点,客户端在ABC三个节点获取成功,然后C挂了又重启 数据丢了。这样其他客户端在节点
    CDE三个节点获取成功,导致了锁冲突
       解决办法:延迟重启,等锁超时之后再重启
    
    3、时间跳跃问题    客户端在ABC获取锁成功,C时间跳跃了,导致锁超时; 其他客户端可以在CDE三个节点获
    取同样的锁  导致锁冲突
       解决办法:不能修改时间

     

  6. zk实现分布式锁

     

     

     

  • ZK和Reids的区别
    Rdis只保证最终一致性,副本间的数据复制是异步进行(Set是写,Get是读,Reids集群一般是读写分离架构,存在主从同步延迟情况),主从切换之后可能有部分数据没有复制过去可能会「丢失锁」情况,故强一致性要求的业务不推荐使用Reids,推荐使用zk。
    Redis集群各方法的响应时间均为最低。随着并发量和业务数量的提升其响应时间会有明显上升(公有集群影响因素偏大),但是极限qps可以达到最大且基本无异常
    
    
    使用ZooKeeper集群,锁原理是使用ZooKeeper的临时节点,临时节点的生命周期在Client与集群的Session结束时结束。因此如果某个Client节点存在网络问题,与ZooKeeper集群断开连接,Session超时同样会导致锁被错误的释放(导致被其他线程错误地持有),因此ZooKeeper也无法保证完全一致。
    ZK具有较好的稳定性;响应时间抖动很小,没有出现异常。但是随着并发量和业务数量的提升其响应时间和qps会明显下降。
     
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值