將該文件放到項目中(任意位置,能引入就行)
根據實際情況將文件中namespace和redis連接方式修改(該文件是以TP5為例)
```
~~~
<?php
namespace app\common\library;
class RedisLock {
private $_redis;
public function __construct() {
$this->_redis = $this->connect();
}
/**
* 獲取鎖
* @param String $lockName 鎖標識
* @param Int $timeout 鎖過期時間
* @return Boolean
*/
public function lock($lockName, $timeout=2){
$identifier=uniqid(); #獲取唯一標識符,作為鎖的值
$timeout=ceil($timeout); #確保是整數
while(true) #循環獲取鎖
{
if($this->_redis->setnx($lockName, $identifier)) #查看$lockName是否被上鎖
{
$this->_redis->expire($lockName, $timeout); #為$lockName設置過期時間,防止死鎖
return $identifier; #返回一維標識符
}
elseif ($this->_redis->ttl($lockName)===-1)
{
$this->_redis->expire($lockName, $timeout); #檢測是否有設置過期時間,沒有則加上(假設,客戶端A上一步沒能設置時間就進程奔潰了,客戶端B就可檢測出來,并設置時間)
}
usleep(0.01); #停止0.001ms
}
return false;
}
/**
* 釋放鎖
* @param String $lockName 鎖標識
* @param String $identifier 鎖值
* @return Boolean
*/
public function unlock($lockName,$identifier){
if($this->_redis->get($lockName)==$identifier) #判斷是鎖有沒有被其他客戶端修改
{
$this->_redis->multi();#開啟事務
$this->_redis->del($lockName); #釋放鎖
$this->_redis->exec();#提交事務
return true;
}
else
{
return false; #其他客戶端修改了鎖,不能刪除別人的鎖
}
}
/**
* 創建redis連接
* @return Link
*/
private function connect(){
try{
$redis = new \Redis();
$redis->connect('127.0.0.1',6379);
//有密碼時設置
// $redis->auth('');
}catch(Exception $e){
throw new Exception($e->getMessage());
return false;
}
return $redis;
}
}
~~~
```
調用
~~~
$lock = new RedisLock();
$lockName = 'snap_up_order';//鎖名(自己隨意寫)
//獲取鎖
$identifier = $lock->lock($lockName);
if($identifier){
//拿到鎖之后寫自己的邏輯代碼
//邏輯代碼執行完后解鎖
$lock->unlock($lockName, $identifier);
}
~~~