1 /** 2 * 解锁 3 * @param [type] $name [description] 4 * @return [type] [description] unlock($name) { ($this->isLocking($name)) { ($this->redisString->deleteKey("Lock:$name")) { ($this->lockedNames[$name]); ; 14 } 15 } ; 17 }
在贴上删除掉所有锁的方法,其实都一个样,多了个循环遍历而已。
1 /** 2 * 释放当前所有获得的锁 3 * @return [type] [description] unlockAll() { = true; => $expireAt) { 9 if (false === $this->unlock($name)) { 10 $allSuccess = false; 11 } 12 } ; 14 }
以上就是用Redis实现分布式锁的整一套思路和代码实现的总结和分享,这里我附上正一个实现类的代码,代码里我基本上对每一行进行了注释,方便大家快速看懂并且能模拟应用。想要深入了解的请看整个类的代码:
1 /** 2 *在redis上实现分布式锁 RedisLock { ; = []; __construct($param = NULL) { 9 $this->redisString = RedisFactory::get($param)->string; 10 } * 13 * 加锁 14 * @param [type] $name 锁的标识名 15 * @param integer $timeout 循环获取锁的等待超时时间,在此时间内会一直尝试获取锁直到超时,为0表示失败后直接返回不等待 16 * @param integer $expire 当前锁的最大生存时间(秒),必须大于0,如果超过生存时间锁仍未被释放,则系统会自动强制释放 17 * @param integer $waitIntervalUs 获取锁失败后挂起再试的时间间隔(微秒) 18 * @return [type] [description] lock($name, $timeout = 0, $expire = 15, $waitIntervalUs = 100000) { ; = time(); = $now + $timeout; = $now + $expire; = "Lock:{$name}"; 31 while (true) { = $this->redisString->setnx($redisKey, $expireAt); ($result != false) { ->redisString->expire($redisKey, $expireAt); ->lockedNames[$name] = $expireAt; ; 41 } = $this->redisString->ttl($redisKey); ttl小于0 表示key上没有设置生存时间(key是不会不存在的,因为前面setnx会自动创建) 47 //如果出现这种状况,那就是进程的某个实例setnx成功后 crash 导致紧跟着的expire没有被调用 ($ttl < 0) { 50 $this->redisString->set($redisKey, $expireAt); 51 $this->lockedNames[$name] = $expireAt; ; 53 } ($timeout <= 0 || $timeoutAt < microtime(true)) break; ($waitIntervalUs); 61 62 } ; 65 } * 68 * 解锁 69 * @param [type] $name [description] 70 * @return [type] [description] unlock($name) { ($this->isLocking($name)) { ($this->redisString->deleteKey("Lock:$name")) { ($this->lockedNames[$name]); ; 80 } 81 } ; 83 } * 86 * 释放当前所有获得的锁 87 * @return [type] [description] unlockAll() { = true; => $expireAt) { 93 if (false === $this->unlock($name)) { 94 $allSuccess = false; 95 } 96 } ; 98 } * 101 * 给当前所增加指定生存时间,必须大于0 102 * @param [type] $name [description] 103 * @return [type] [description] expire($name, $expire) { ($this->isLocking($name)) { = max($expire, 1); ($this->redisString->expire("Lock:$name", $expire)) { ; 113 } 114 } ; 116 } * 119 * 判断当前是否拥有指定名字的所 120 * @param [type] $name [description] 121 * @return boolean [description] isLocking($name) { (isset($this->lockedNames[$name])) { (string)$this->lockedNames[$name] = (string)$this->redisString->get("Lock:$name"); 128 } ; 131 } 132 133 }
Redis实现分布式锁
(二)用Redis实现任务队列的代码分析
(1)任务队列,用于将业务逻辑中可以异步处理的操作放入队列中,在其他线程中处理后出队
(2)队列中使用了分布式锁和其他逻辑,保证入队和出队的一致性