-
对于批量操作进行加锁,防止重复提交和数据库冲突
-
register_shutdown_function() 函数,register_shutdown_function 用于注册一个在脚本执行完毕或发生致命错误时调用的函数。这意味着 register_shutdown_function 注册的函数会在脚本的正常执行流程结束后调用,而不是立即执行。代码的执行顺序如下:
- 注册一个 shutdown 函数,该函数在脚本结束时调用 LockService::remove($lockKey)。
- 执行 $value = 1;。
- 脚本继续执行后续的代码。
- 当脚本执行完毕或发生致命错误时,调用注册的 shutdown 函数。
$lockKey = 'store:pop:plant:operation'.$storeId;
//判断锁是否存在
if (LockService::has($lockKey, 5)) {$this->error('正在处理,请勿重复提交');
}
//register_shutdown_function
register_shutdown_function(function ($lockKey) {LockService::remove($lockKey);
}, $lockKey);
LockService服务类
<?phpnamespace app\common\service;class LockService
{/*** 判断是否有锁* @param string $key 锁Key* @param int $ttl 锁时间(秒)* @param bool $refreshTtl 是否重置锁时间* @return bool* @throws \RedisException*/public static function has(string $key, int $ttl = 5, bool $refreshTtl = true): bool{$res = RedisService::handle()->incr(self::buildKey($key));if ($refreshTtl || $res === 1) {RedisService::handle()->expireAt(self::buildKey($key), time() + $ttl);}return $res !== 1;}/*** 移除锁* @param string $key* @return void* @throws \RedisException*/public static function remove(string $key){RedisService::handle()->del(self::buildKey($key));}/*** 获取锁定次数* @param string $key* @return false|mixed|\Redis|string* @throws \RedisException*/public static function times(string $key){return RedisService::handle()->get(self::buildKey($key));}private static function buildKey(string $key): string{return 'lock:' . $key;}
}