zoukankan      html  css  js  c++  java
  • 基于redis的分布式锁

    <?php
    /**
     * 基于redis的分布式锁
     *
     * 参考开源代码:
     * http://nleach.com/post/31299575840/redis-mutex-in-php
     *
     * https://gist.github.com/nickyleach/3694555
     */
    pc_base::load_sys_class('cache_redis', '', 0);
    
    
    class dist_key_redis {
    
        //锁的超时时间
        const TIMEOUT = 20;
    
        const SLEEP = 100000;
    
        /**
         * Stores the expire time of the currently held lock
         * 当前锁的过期时间
         * @var int
         */
        protected static $expire;
    
        public static function getRedis()
        {
            return new cache_redis();
        }
    
        /**
         * Gets a lock or waits for it to become available
         * 获得锁,如果锁被占用,阻塞,直到获得锁或者超时
         *
         * 如果$timeout参数为0,则立即返回锁。
         * 
         * @param  string    $key        
         * @param  int        $timeout    Time to wait for the key (seconds)
         * @return boolean    成功,true;失败,false
         */
        public static function lock($key, $timeout = null){
            if(!$key)
            {
                return false;
            }
     
            $start = time();
    
            $redis = self::getRedis();
     
            do{
                self::$expire = self::timeout();
                
                if($acquired = ($redis->setnx("Lock:{$key}", self::$expire)))
                {
                    break;
                }
    
                if($acquired = (self::recover($key)))
                {
                    break;
                }
                if($timeout === 0) 
                {
                    //如果超时时间为0,即为
                    break;
                }
     
                usleep(self::SLEEP);
    
            } while(!is_numeric($timeout) || time() < $start + $timeout);
     
            if(!$acquired)
            {
                //超时
                return false;
            }
     
            return true;
        }
     
        /**
         * Releases the lock
         * 释放锁
         * @param  mixed    $key    Item to lock
         * @throws LockException If the key is invalid
         */
        public static function release($key){
            if(!$key)
            {
                return false;
            }
    
            $redis = self::getRedis();
     
            // Only release the lock if it hasn't expired
            if(self::$expire > time()) 
            {
                $redis->del("Lock:{$key}");
            }
        }
     
        /**
         * Generates an expire time based on the current time
         * @return int    timeout
         */
        protected static function timeout(){
            return (int) (time() + self::TIMEOUT + 1);
        }
     
        /**
         * Recover an abandoned lock
         * @param  mixed    $key    Item to lock
         * @return bool    Was the lock acquired?
         */
        protected static function recover($key){
    
            $redis = self::getRedis();
    
            if(($lockTimeout = $redis->get("Lock:{$key}")) > time())
            {
                //锁还没有过期
                return false;
            }
     
            $timeout = self::timeout();
            $currentTimeout = $redis->getset("Lock:{$key}", $timeout);
     
            if($currentTimeout != $lockTimeout)
            {
                return false;
            }
     
            self::$expire = $timeout;
            return true;
        }
    }
    
    ?>
  • 相关阅读:
    taro 填坑之路(一)taro 项目回顾
    Redux遵循的三个原则是什么?
    解释一下 Flux
    MVC框架的主要问题是什么?
    与 ES5 相比,React 的 ES6 语法有何不同?
    你了解 Virtual DOM 吗?解释一下它的工作原理
    DOM 事件有哪些阶段?谈谈对事件代理的理解
    CSS:用Less实现栅格系统
    .NET:国际化和本地化
    自定义工作流 之 模型设计与实现
  • 原文地址:https://www.cnblogs.com/siqi/p/3959517.html
Copyright © 2011-2022 走看看