175 lines
4.6 KiB
PHP
175 lines
4.6 KiB
PHP
<?php
|
|
/**锁操作
|
|
* Created by gzhq.
|
|
* User: 252378189@qq.com
|
|
* Date: 2018/3/18
|
|
* Time: 20:18
|
|
*/
|
|
class gzhq_lock{
|
|
const LOCK_TYPE_DB = 'SQLLock';
|
|
const LOCK_TYPE_FILE = 'FileLock';
|
|
const LOCK_TYPE_MEMCACHE = 'MemcacheLock';
|
|
|
|
private $_lock = false;
|
|
private static $_supportLocks = array('FileLock', 'SQLLock', 'MemcacheLock','RedisLock');
|
|
|
|
public function __construct($type, $options = array()){
|
|
if(false == empty($type)) {
|
|
$this->createLock($type, $options);
|
|
}
|
|
}
|
|
public function createLock($type, $options=array()){
|
|
if(false == in_array($type, self::$_supportLocks)){
|
|
throw new Exception("not support lock of ${type}");
|
|
}else{
|
|
$this->_lock = new $type($options);
|
|
}
|
|
}
|
|
public function getLock($key, $timeout = in_lock::EXPIRE){
|
|
if (false == $this->_lock instanceof in_lock) {
|
|
throw new Exception('false == $this->_lock instanceof ILock');
|
|
}
|
|
$this->_lock->getLock($key, $timeout);
|
|
}
|
|
|
|
public function unLock($key){
|
|
if (false == $this->_lock instanceof in_lock) {
|
|
throw new Exception('false == $this->_lock instanceof ILock');
|
|
}
|
|
$this->_lock->unLock($key);
|
|
}
|
|
}
|
|
//必须实现的接口
|
|
interface in_lock{
|
|
const EXPIRE = 5;
|
|
public function getLock($key, $timeout=self::EXPIRE);
|
|
public function unLock($key);
|
|
}
|
|
|
|
//创建文件锁
|
|
class FileLock implements in_lock{
|
|
private $_fp;
|
|
private $_lockPath;
|
|
//创建锁
|
|
/*
|
|
* $options = '';//文件存放路径
|
|
*/
|
|
public function __construct($options){
|
|
if (isset($options) && is_dir($options)) {
|
|
$this->_lockPath = $options.'/';
|
|
}else{
|
|
$this->_lockPath = WEBPATH_DIR.'/cache/';
|
|
}
|
|
}
|
|
public function getLock($key, $timeout=self::EXPIRE){
|
|
$file = md5($key);
|
|
$tmp_mypath = $this->_lockPath .$file.'.lock';
|
|
$this->_fp = fopen($tmp_mypath,"w+");
|
|
if ($this->_fp === false) {
|
|
return false;
|
|
}
|
|
$waitime = 10;
|
|
$totalWaitime = 0;
|
|
$timeout *=1000000;
|
|
while (!flock($this->_fp,LOCK_EX | LOCK_NB)) { // 加锁
|
|
$totalWaitime +=$waitime;
|
|
if ($totalWaitime > $timeout) { // 超时逻辑
|
|
fclose($this->_fp);
|
|
return false;
|
|
}
|
|
usleep($waitime);
|
|
}
|
|
return true;
|
|
}
|
|
public function unLock($key){
|
|
flock($this->_fp,LOCK_UN);
|
|
fclose($this->_fp);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
//创建mysql锁
|
|
class SQLLock implements in_lock{
|
|
private $_db;
|
|
//创建锁
|
|
/*
|
|
* $options='';//数据库连接
|
|
*/
|
|
public function __construct($options){
|
|
$this->_db = $options;
|
|
}
|
|
|
|
public function getLock($key, $timeout=self::EXPIRE){
|
|
$sql = "SELECT GET_LOCK('KEY".$key."', '".$timeout."')";
|
|
$res = $this->_db->query($sql);
|
|
return $res;
|
|
}
|
|
|
|
public function unLock($key){
|
|
$sql = "SELECT RELEASE_LOCK('KEY".$key."')";
|
|
return $this->_db->query($sql);
|
|
}
|
|
}
|
|
|
|
//创建Memcache锁
|
|
class MemcacheLock implements in_lock{
|
|
private $memcache;
|
|
//创建锁
|
|
/*
|
|
* $options='';//Memcache连接
|
|
*/
|
|
public function __construct($options){
|
|
|
|
$this->memcache = $options;
|
|
}
|
|
public function getLock($key,$timeout=self::EXPIRE){
|
|
$waitime = 10;
|
|
$totalWaitime = 0;
|
|
$time = $timeout*1000000;
|
|
while (false == $this->memcache->add("KEY".$key, 1, $timeout)) {
|
|
usleep($waitime);
|
|
$totalWaitime += $waitime;
|
|
if ($totalWaitime >= $time){
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
public function unLock($key){
|
|
$this->memcache->delete("KEY".$key);
|
|
return true;
|
|
}
|
|
}
|
|
//创建redis锁
|
|
class RedisLock implements in_lock{
|
|
private $redis;
|
|
//创建锁
|
|
/*
|
|
* $options='';//Redis连接
|
|
*/
|
|
public function __construct($options){
|
|
$this->redis = $options;
|
|
}
|
|
public function getLock($key, $timeout=self::EXPIRE){
|
|
$waitime = 10;//延时多久检查
|
|
$totalWaitime = 0;//当前等了多久
|
|
$time = $timeout*1000000;//把超时时间从毫秒改为微秒
|
|
while(false==$this->redis->psetex("KEY".$key,$time,1)){
|
|
usleep($waitime);
|
|
$totalWaitime += $waitime;
|
|
if ($totalWaitime >= $time){
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
|
|
}
|
|
public function unLock($key){
|
|
$this->redis->delete("KEY".$key);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
|