最近有个项目用到了锁,直接想到了redis,在网上查看了一下案列,总感觉不是特别符合需求,索性自己写了一个。
供大家参考,有问题请留意,共同学习提高。
不多说,直接上代码:
<?php
/**
* Class redis_lock
*
* 单机redis 分布式锁
*/
class redis_lock
{
public $redis;
public function __construct() //连接Redis服务器
{
$this->redis = new \redis();
$this->redis->connect('127.0.0.1', 6379);
// $this->redis->auth('123456');
// $this->redis->select(12);
}
/**
* 单台Redis设置锁
*
* @param string $key
* @param int $expire
* @return bool
*/
public function setLock($key, $expire = 10)
{
$res = $this->check_key($key);
if (!$res) {
return false;
}
$res = $this->check_expire($expire);
if (!$res) {
return false;
}
$res = $this->redis->set('Redis:Lock:' . $key, time() + $expire, ['nx', 'ex' => $expire]);
if (!$res) {
return false;
}
return true;
}
/**
* 校验有效期
*
* @param mixed $expire
* @return int
*/
public function check_expire($expire)
{
if (!is_numeric($expire)) {
return false;
}
return true;
}
/**
* 校验$key
*
* @param mixed $key
* @return bool
*/
public function check_key($key)
{
if (!is_string($key) && !is_int($key)) {
return false;
}
//允许数字、英文字符、下划线、英文冒号
preg_match('/^[\w\:]*+$/', $key, $p_key);
if (!isset($p_key[0]) || $p_key[0] != $key) {
return false;
}
return true;
}
/**
* 单台Redis设备锁,如果不能进入将等待
*
* @param string $key
* @param int $expire
* @param int $wait_seconds
* @return bool
*/
public function setLockAndWait($key, $expire = 10, $wait_seconds = 10)
{
/*如果是webserver,并且session服务器是文件或者memcache,最好加上这一行
也可以用session_commit(),解除session锁。如果session服务器是redis,就不用了*/
session_write_close();
$time = time();
$wait_time = $time + $wait_seconds;
while (true) {
$res = $this->setLock($key, $expire);
if ($res) {
return $res;
}
if ($time >= $wait_time) {
return false;
}
usleep(500); //等待微妙数
}
}
/**
* 单台Redis删除锁
*
* @param string $key
* @return bool
*/
public function delLock($key)
{
$res = $this->redis->del($key);
if ($res === false) {
return false;
}
return true;
}
}
$redis = new redis_lock();
$res = $redis->setLock('111');
$redis->delLock('111');
var_dump($res);
exit;
?>