php,redis分布式锁防并发

解决死锁

  如果只用SETNX命令设置锁的话,如果当持有锁的进程崩溃或删除锁失败时,其他进程将无法获取到锁,问题就大了。

解决方法是在获取锁失败的同时获取锁的值,并将值与当前时间进行对比,如果值小于当前时间说明锁以过期失效,进程可运用Redis的DEL命令删除该锁。

setnx的作用和memcache的add方法类似

class rediss
    {
        private $redis;
        function __construct()
        {
            $this->redis= $this->redis();
        }
        public function redis(){
            $redis = new Redis();
            $redis->connect('127.0.0.1','6379') or die('con not redis');
            $redis->auth('1234');
            return $redis;
        }
        public function lock($key,$expire){

            $is_lock = $this->redis->setnx($key,(time()+$expire));
            
            //如果setnx赋值成功,则$is_lock返回1,否则返回空
            $is_lock=!empty($is_lock) ? 'true' : 'false';
            if($is_lock=='true'){
                $this->redis->expire($key,$expire); //给键值加有效时间
            }
            return $is_lock;
        }
        public function delLock($key){
            return $this->redis->del($key);
        }
    }
    $bb = new rediss();

    $key='hua'; //键名
    $val=5;//传的参数
    
    $lock = $bb->lock($key,$val);
    if($lock=='false'){
        $hua = $bb->redis()->get($key);
        if(time()>$hua){
            $bb->delLock($key);
            echo "删除";
        }
    }else{
        echo $bb->lock($key,$val);
        //该区域进行sql操作
    }

class rediss{private $redis;function __construct(){$this->redis= $this->redis();}public function redis(){$redis = new Redis();$redis->connect('127.0.0.1','6379') or die('con not redis');$redis->auth('1234');return $redis;}public function lock($key,$expire){

$is_lock = $this->redis->setnx($key,(time()+$expire));//如果setnx赋值成功,则$is_lock返回1,否则返回空$is_lock=!empty($is_lock) ? 'true' : 'false';if($is_lock=='true'){$this->redis->expire($key,$expire); //给键值加有效时间}return $is_lock;}public function delLock($key){return $this->redis->del($key);}}$bb = new rediss();

$key='hua'; //键名$val=5;//传的参数$lock = $bb->lock($key,$val);if($lock=='false'){$hua = $bb->redis()->get($key);if(time()>$hua){$bb->delLock($key);echo "删除";}}else{echo $bb->lock($key,$val);//该区域进行sql操作}