<?php
use Swoole\Timer;
function lockerRun(Closure $closure, string $lock_key, string $lock_val, int $expire = 30)
{
$result = new Result();
$redis = new \Redis();
$lock = $redis->set($lock_key, $lock_val, ['nx', 'ex' => $expire]);
if ($lock) {
$result->setLock(true);
// 计算定时器执行时间
$timer = intdiv($expire, 3) ?: 1;
$ms = $timer * 1000;
$timer_id = Timer::tick($ms, function () use ($redis, $lock_key, $lock_val, $expire) {
$script = "
local lock_key = KEYS[1]
local ttl = redis.call('TTL', lock_key)
if ttl > 0 then
local lock_val = redis.call('GET', lock_key)
if lock_val == ARGV[1] and ttl <= tonumber(ARGV[2]) then
redis.call('EXPIRE', lock_key, tonumber(ARGV[3]))
return 1
else
return 0
end
else
return 0
end";
$redis->eval($script, [$lock_key, $lock_val, $expire - intdiv($expire, 3), $expire], 1);
});
try {
// 执行业务逻辑
$result->setResult($closure());
return $result;
} catch (\Throwable $e) {
throw $e;
} finally {
$timer_id && Timer::clear($timer_id);
// 锁删除
$script = "
local lock_key = KEYS[1]
local lock_val = redis.call('GET', lock_key)
if lock_val == ARGV[1] then
redis.call('DEL', lock_key)
return 1
else
return 0
end";
$redis->eval($script, [$lock_key, $lock_val], 1);
}
}
return $result;
}
php在swoole中redis加锁续期
于 2024-03-28 17:41:29 首次发布