redis分布式锁

来源:互联网 发布:社区控烟网络会议记录 编辑:程序博客网 时间:2024/06/03 19:55

理论: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

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

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

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

原创粉丝点击