redis分布式锁

理论:http://blog.csdn.net/ugg/article/details/41894947
代码:http://blog.csdn.net/he90227/article/details/69568702
个人理解:
redis分布式锁主要是从判断(key,value)是否存在来断定是否让线程获取到锁,如果获得锁,执行业务,未获取到锁,不执行业务,阻止并发线程出错。

看自己写的伪代码:

public void lock(String lockKey, String currentThreadTime){
        boolean lock = false;//初始化未获取到锁
        boolean success = SETNX(lockKey, currentThreadTime);
        if(success){
            //通过命令setnx即获取到了锁(这个资源锁被释放,或者被redis因过期del)
            expire(currentThreadTime);//设置过期时间,防止因当前线程获取锁后,突然挂掉而导致锁不被释放
            lock = true;//代表获取到锁
        }else{
            //说明该资源被其他线程占了锁
            valueTimeStr = GET(lockKey);//获取到锁的时间戳值
            if(valueTimeStr != null && valueTimeStr < systemCurrentTime){
                //该锁未被其他线程del且过期----A
                oldValueTimeStr = GETSET(lockKey,currentThreadTime);

                //当前线程发现锁过期,决定尝试获取用getset获取锁
                if(oldValueTimeStr != null && valueTimeStr.equals(oldValueTimeStr)){
                    //getset命令去获取旧的时间,看从A进来这段代码期间,有没有其他线程也发现过期而del或者修改掉了锁的值
                    lock = true;//获得锁
                }else{
                    //虽然GET的时候发现锁过期了,但是在准备获取这个锁时,其他线程抢先del或者修改了lockKey的值
                    sleep(200);//线程死等200毫秒,再看下一次循环
                }
            }else{
                //因过期redis服务器删了锁,或者其他线程发现锁过期删了锁
                sleep(200);//等待下一次循环
            }
        }
    }

总结:1、获得锁的两个状态:
a.(lockKey,value)这对键值对未创建,也就是说没有其他线程正在占用该锁时
b. lockKey被占用,但是过期了,且未被其他线程抢先占有,代码片段如下:
oldValueTimeStr != null && valueTimeStr.equals(oldValueTimeStr)
2、锁设置过期时间是为了防止死锁,假设C1线程SETNX成功了,但是突然挂掉了,一直不释放锁,其他线程只能干等,造成死锁
3、使用到的三个命令:
SETNX,GET,GETSET,DEL
4、关于GETSET,如果有其他线程获取了锁,设置了新的过期时间,那么当前线程GETSET并不会获取锁,此时又修改了时间,会不会导致过期时间一直增长,导致锁永远不过期,答案是不会,当两个线程在getset这里进行竞争时,说明两个线程设置的时间差也很小,不会影响业务

问题思考:
1、过期时间设置多长合适,如果业务时间大于锁过期时间,线程C1获取锁后执行业务时,线程C2发现锁过期,然后通过GETSET获取了锁,进而执行业务,那么此时,C1,C2同时执行业务,是不是造成了并发的情况
2、SETNX失败是否直接让线程等待锁过期,被服务器删除后尝试,而不用进行GETSET后面的操作,直接等待

分析:
问题1:如果业务的执行时间大于锁过期时间,说明锁过期时间设置过短,需要设置更加合理的过期时间,纯属于业务时间评估问题
问题2:不可行,过期键删除默认是定期删除,懒删除两种,如果定期没有删除,轮询时间过长,那么线程会等待较长时间,懒删除,如果不去执行get,getset命令,其他线程不去访问,那就锁一直在

上面两个问题的关键就是,是否存在,线程1获取到锁,但是业务还没执行完,但是锁过期了?

再加一个流程图:
这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值