实现功能
可以根据方法名(__FUNCTION__、__METHOD__),或者方法名+用户id等多种自定义键值进行加锁。
解锁方式有三种:
1.设置锁时间过期自动解锁
2.控制器销毁后自动解锁
3.手动解锁
原理
1.加锁
/**
*加锁代码
* @param $key 自定义键值
* @param int $expireTime 锁过期时间
* @return bool|mixed 成功返回锁唯一id,失败返回false或抛出错误
* @throws \Exception
*/
public static function addLock($key, $expireTime = self::LOCK_DEFAULT_EXPIRE_SECOND)
{
//传入参数判断
if (empty($key) || $expireTime <= 0) {
return false;
}
//创建redis实例
$redisClient = self::redis();
//获取唯一锁id
$uniqueLockId = self::getUniqueLockId();
//生成最终key
$finalKey = sprintf(self::LOCK_KEY, $key);
//使用setnx 进行锁判断
$LockRet = $redisClient->set($finalKey, $uniqueLockId, ['nx', 'ex'=>$expireTime]);
if($LockRet == false) {
//加锁失败
throw new \Exception('redis lock failed');
}
//返回唯一锁id(解锁的时候需要用到)
return $uniqueLockId;
}
2.解锁
/**
* 解锁操作
* @param $key 传入锁key
* @param $uniqueLockId 传入锁唯一id
* @return bool 返回是否成功
*/
public static function releaseLock($key, $uniqueLockId)
{
//参数验证
if (empty($key) || empty($uniqueLockId)) {
return false;
}
//获取redis实例
$redisClient = self::redis();
//获取最终key
$finalKey = sprintf(self::LOCK_KEY, $key);
//监听期间锁是否被改变
$redisClient->watch($finalKey);
if ($uniqueLockId == $redisClient->get($finalKey)) {
$redisClient->multi()->del($finalKey)->exec();
return true;
}
$redisClient->unwatch();
return false;
}