php redis 锁实现原理,Redis-PHP锁实现

PHP的文件锁在单服务器的时候使用是什么任何问题的,当多服务时,PHP的文件锁就无法满足需求,一个服务器锁了另外一台服务器并且不知道有锁,从而导致锁失效,

而Redis共享锁可以满足。

8805612c91b45573f3ac7df883dfdcab.png

1、实现PHP的Redis锁

1) 首先安装好Redis服务

2) 下载PHP连接Redis组件,下载地址https://github.com/sash/php-redis

3)实现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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值