PHP代码:
Python代码: https://github.com/huangz1990/riacn-code
private $lockName = "lock:redis_lock_name";
private $acquireTimeOut = 3;//3秒内没有获得锁 返回false
private $lockTimeOut = 3;//锁过期时间
/**
* 原版获得锁
* redis lock
*/
public function redisLock()
{
$uniqueId = uniqid("redisUuid_");
$time = time();
$end = $time + $this->acquireTimeOut;
while ($time < $end) {
if ($this->setnx($this->lockName, $uniqueId)){
$this->setTimeout($this->lockName, $this->lockTimeOut);
return $uniqueId;
}else if (!$this->ttl($this->lockName)) {
$this->setTimeout($this->lockName, $this->lockTimeOut);
}
usleep(1000);
}
return false;
}
/**
* 原本 释放锁
* @param unknown $uniqueId
*/
public function releaseLock($uniqueId) {
while (true) {
try {
$this->watch($this->lockName);
if ($this->get($this->lockName) == $uniqueId){
$this->multi(\Redis::PIPELINE);
$this->delete($this->lockName);
$this->exec();
return true;
}
$this->unwatch($this->lockName);
break;
} catch (\Exception $e) {
}
}
return false;
}
/** var_dump($redis->releaseLockByLua($redis->redisLockByLua()));die;
* lua 版 获得锁
* redis lock lua
* @return string|boolean
*/
public function redisLockByLua()
{
$uniqueId = uniqid("redisUuid");
$time = time();
$end = $time + $this->acquireTimeOut;
$acquired = false;
while (($time < $end) && !$acquired) {
$func = "eval";
$acquired = $this->eval("
if (redis.call('exists', ARGV[1]) == 0) then
return redis.call('setex', ARGV[1], ARGV[2], ARGV[3])
end
", [$this->lockName, $this->lockTimeOut, $uniqueId]);
usleep(1000 * !$acquired);
if ($acquired){
return $uniqueId;
}
}
return false;
}
/**
* lua 版 释放锁
* @param string $uniqueId
*/
public function releaseLockByLua($uniqueId) {
return $this->eval("
if (redis.call('get', ARGV[1]) == ARGV[2]) then
return redis.call('del', ARGV[1]) or true
end
", [$this->lockName, $uniqueId]);
}
/**
* lua 版 获取公平信号量
* @param unknown $semname
* @param number $limit
* @param number $timeout
*/
public function redisAcquireSemaphore($semname, $limit = 10, $timeout = 10) {
list($micro, $second) = explode(' ', microtime());
$time = $second + $micro;
$uniqueId = uniqid("redisUuidSem");
return $this->eval("
redis.call('zremrangebyscore', ARGV[1], 0, ARGV[2])
if redis.call('zcard', ARGV[1]) < tonumber(ARGV[3]) then
redis.call('zadd', ARGV[1], ARGV[4], ARGV[5])
return ARGV[5]
end
", [$semname, $time - $timeout, $limit, $time, $uniqueId]);
}
/**
* lua 版 刷新公平信号量
* @param unknown $semname
* @param unknown $uniqueId
*/
public function refreshSemaphore($semname, $uniqueId) {
list($micro, $second) = explode(' ', microtime());
$time = $second + $micro;
return $this->eval("
if redis.call('zscore', ARGV[1], ARGV[2]) then
return redis.call('zadd', ARGV[1], ARGV[3], ARGV[2]) or true
end
", [$semname, $uniqueId, $time]);
}
/**
* 释放公平信号量
* @param unknown $semname
* @param unknown $uniqueId
*/
public function releaseFairSemaphore($semname, $uniqueId) {
return $this->zRem($semname, $uniqueId);
}
/**
测试用例
var_dump($sem1 = $redis->redisAcquireSemaphore("semname", 2));
var_dump($sem2 = $redis->redisAcquireSemaphore("semname", 2));
var_dump($sem3 = $redis->redisAcquireSemaphore("semname", 2));
echo "<br><br>";
var_dump($redis->refreshSemaphore("semname", $sem1));
echo "<br><br>";
var_dump($redis->releaseFairSemaphore("semname", $sem1));
var_dump($redis->releaseFairSemaphore("semname", $sem2));
var_dump($redis->releaseFairSemaphore("semname", $sem3));
die;
//redis lock
var_dump($redis->releaseLockByLua($redis->redisLockByLua()));die;
var_dump($redis->releaseLock($redis->redisLock()));die;
*
*/
Python代码: https://github.com/huangz1990/riacn-code