PHP的文件锁在单服务器的时候使用是什么任何问题的,当多服务时,PHP的文件锁就无法满足需求,一个服务器锁了另外一台服务器并且不知道有锁,从而导致锁失效, 而Redis共享锁可以满足。
1、实现PHP的Redis锁
1) 首先安装好Redis服务
2) 下载PHP连接Redis组件,下载地址https://github.com/sash/php-redis
3)实现php代码
<?php
require "Redis.php";
class Lock {
protected $db;
/**
* @var 锁时间
*/
protected $timeout = 10;
/**
* @var 最大锁时间
*/
protected $maxTimeout;
/**
* @var 过期时间
*/
protected $expireTime = 0;
/**
* @var 键
*/
protected $key;
/**
* 读取超时时间
*/
public function getTimeOut()
{
return $this->timeout + time();
}
/**
* 设置超时时间
*/
public function setTimeout($second)
{
$this->timeout = $second > $this->maxTimeout ? $this->maxTimeout : $second;
return true;
}
/**
* 存储当前锁的过期时间,用于解锁
*/
public function setExpireTime($time)
{
$this->expireTime = $time;
return true;
}
/**
* 获取当前锁的过期时间,用于解锁
*/
public function getExpireTime()
{
return $this->expireTime;
}
public function __construct($maxTimeout = 120)
{
$this->db = new Redis(); //这里可以做成单例
$this->maxTimeout = $maxTimeout;
}
/**
* 锁
* @param string $key 锁名
* @param int $waitTimeOut 等待时间,默认是阻塞(一直等待)
*/
public function lock($key, $waitTimeOut = null)
{
$key = $this->getKey($key);
if (!$key || $this->key) return false;
$this->key = $key; //如果设置了超时时间
if (is_numeric($waitTimeOut)) $waitTimeOut = time() + $waitTimeOut;
do {
if ($lockStatus = $this->db->setnx($this->key, $this->getTimeOut())) {
if ($this->db->expire($this->key, $this->maxTimeout)) {
break;
}
}
if ($lockStatus = $this->recover()) {//如果覆盖成功
break;
}
usleep(200); //睡眠处理
} while(!is_numeric($waitTimeOut) || $waitTimeOut >= time());
if (!$lockStatus) return false;
$this->setExpireTime($this->db->get($key)); //设置当前的过期时间, 用于释放所
return true;
}
/**
* 尝试覆盖已有的锁
*/
protected function recover()
{
if (($expireTime = $this->db->get($this->key)) > time()) { //如果没有过期,直接返回
return false;
}
if ($currentTime = $this->db->getset($this->key, $this->getTimeOut())) {
$this->db->expire($this->key, $this->getMaxTimeout());
}
if ($currentTime != $expireTime) {//说明设置当前覆盖成功
return false;
}
return true;
}
/**
* 解锁
*/
public function unlock()
{
if ($this->getExpireTime() >= time() && !$this->db->del($this->key)) {
return false;
}
$this->key = null;
return true;
}
/**
* 获取锁名
*/
protected function getKey($key)
{
if (empty($key) || !is_string($key)) {
return false;
}
return "Lock:{$key}";
}
}
//测试代码,开多个页面进行测试
$timeOut = !empty($_GET['t']) ? (int)$_GET['t'] : null; //等待时间不传就是阻塞
$lock = new Lock();
if (!$lock->lock('test3', $timeOut)) {
echo 'Locking';
exit();
}
sleep(6);
echo 'ok';
$lock->unlock();
?>
版权声明:未经博主允许不得转载。http://smister.com/post-48/redis-php-lock.html
飞翔 :
2021-07-24 10:12:56 回复
飞翔 :
2021-07-24 10:12:25 回复
时间冲淡一切 :
2020-12-12 15:57:36 回复
时间冲淡一切 :
2020-12-12 15:57:15 回复
何ゾンチェン :
2019-03-18 17:40:50 回复
发表评论
热门标签
帖子分类
热门帖子