php redis 常见应用 并发锁。(悲观锁)

redis 实现悲观锁。

原理,进去则抢锁,抢失败了 等一秒再抢,再等一秒再抢,如此反复循环。

解锁就是删掉对应的键。  

/**
 * 实现redis 悲观锁
 * User: babytuo
 */
Class RedisLock {

    public $expire = 2;

    public function test(){

         $this->lock("test1");
         echo "111";
    }


    public function lock($key){

        $redis = self::createRedisObj();
        $now = time();

        /**  理解setnx
        若给定的 key 已经存在,则 SETNX 不做任何动作。
        SETNX 是『SET if Not eXists』(如果不存在,则 SET)的简写。
         */
        //抢锁.
        $isLock = $redis->setnx($key , time() + $this->expire);  //设为过期时间.

        //不成功
        while ( ! $isLock) {
            $now++;
            $time = $now + $this->expire;

            //再重新创建
            $lock = $redis->setnx($key, $time);
            if ($lock == 1 || ($now > $redis->get($key) && $now > $redis->getset($key, $time))) {//争锁成功后,设置新的过期时间.
                break;
            } else {
                sleep(1);//0.5s
            }
        }
        return true;
    }

    /**
     * 解锁
     * @param type $flag
     * @return boolean
     */
    public function unlock($key) {
        $redis = self::createRedisObj();
        $redis->del($key);
        return true;
    }

    /**
     * 检查锁是否存在
     * @param $key
     * @return bool
     */
    public function checklock($key){
        $redis = self::createRedisObj();
        return $redis->exists($key);
    }





    public static $_redis;
    /**
     * 创建一个redis 对象.
     * @return Redis
     */
    public static function createRedisObj(){
        if( ! self::$_redis){
            $redis = new Redis();
            $info =  Yii::app()->cache->servers[0];  //读取配置
            $host = $info["host"];
            $port = $info["port"];
            $redis->connect($host,$port);
            $redis_db =    Yii::app()->settings->get('system' , 'redis_db');  //设置默认库
            $redis->select($redis_db);
            self::$_redis = $redis;
        }
        return self::$_redis;
    }


}

猜你喜欢

转载自www.cnblogs.com/babytuo/p/9001983.html