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操作}