防止并发
$biz = '发送贵重物品';
$lockId = $this->getLockId($label1, $label2);
//获取锁
$claimLock = CacheUtil::acquireRedLock($biz, $lockId);
if (!$claimLock) {
//TODO ....
var_dump('获取锁失败');
}
try {
//TODO 业务逻辑 ....
//TODO 业务条件判断失败 ....
if (isset($condition1) && $condition1 !== true) {
// 释放锁
CacheUtil::releaseLock($this->bizName, $lockId);
var_dump('业务条件未达标');
die();
}
// 释放锁
CacheUtil::releaseLock($this->bizName, $lockId);
} catch (Exception $e) {
// 释放锁
CacheUtil::releaseLock($this->bizName, $lockId);
throw $e;
}
function getLockId(int $label1, string $label2): string
{
return sprintf("%d_%s", $label1, $label2);
}
function acquireRedLock(string $prefix, string $id): bool
{
$lockid = self::buildLockId($prefix, $id);
$luaScript = <<<SCRIPT
local sx = redis.call('SETNX',KEYS[1],ARGV[1]);
if(sx>0)
then
redis.call('EXPIRE',KEYS[1],ARGV[2]);
end
return sx;
SCRIPT;
$rdsConn = getRedisConnection($lockid);
try {
return h_retry(3, function () use ($lockid, $luaScript, $rdsConn) {
$callRet = $rdsConn->eval($luaScript, [$lockid, time(), 6], 1);
if (!$callRet) {
throw new \Exception('获锁失败');
}
return true;
});
} catch (\Throwable $e) {
}
return false;
}