<?php
namespace App\Http\Controllers\lock;
use App\Http\Controllers\Controller;
class LockController extends Controller
{
private $redis;
private $lockId; //记录加锁客户端的id
public function __construct($redis)
{
$this->redis = $redis;
}
/**
* @param string $scene 业务场景
* @param int $expire 锁过期时间
* @param int $retry 等待尝试次数
* @param int $sleep 等待时间
* @return bool
*/
public function lock($scene='seckill',$expire=5,$retry=5,$sleep=1000000){
//同一时刻只能有一个用户持有锁,并且不能出现死锁
$res=false;
while($retry-- > 0){
$value=uniqid();//生成不重复的字符串
$res=$this->redis->set($scene,$value,['NX','EX'=>$expire]);
if($res){
$this->lockId[$scene] = $value;
break;
}
var_dump('尝试获取锁'.PHP_EOL) ;
usleep($sleep);
}
return $res;
}
public function unlock($scene){
$script=<<<LUA
local key=KEYS[1];
local value=ARGV[1];
if(redis.call('get',key) == value)
then
return redis.call('del',key)
end
LUA;
//能够删除自己的锁,而不应该删除别人的锁
if(isset($this->lockId[$scene])){
$id = $this->lockId[$scene];
// $value = $this->redis->get($scene);
//
// if($value == $id){
// return $this->redis->del($scene);
// }
$this->redis->eval($script,[$scene,$id]);
}
return false;
}
}