locks没有,除非您在被调用的脚本中处理此情况,否则它不会中断。解决该问题的一种常见方法是使用
或实现mutualublufusion.。 有许多实施PHP锁定的方法,并且没有“最佳”方法。您是否可以选择最适合您平台上可用的后端的一种,或为不同平台甚至不同的用例实施多个储物柜。当心,您应该确保您始终在同一主机上使用相同的储物柜作为特定作业!
可以用作锁定后端的流行工具中的一些:
Flock
GET_LOCK
,IS_USED_LOCK
RELEASE_LOCK
)
示例
以下代码实现了基于Phpredis
namespace Acme;
class Factory {
/// @var \Redis
private static $redis;
public static function redis() {
if (!static::$redis) {
try {
static::$redis = new \Redis();
// In practice you should fetch the host from a configuration object.
static::$redis->pconnect('/tmp/redis.sock');
} catch (\Exception $e) {
trigger_error($e->getMessage(), E_USER_WARNING);
return false;
}
}
return static::$redis;
}
/**
* @param mixed $id ID of a job or group of jobs
* @return AbstractLocker
*/
public static function locker($id) {
return new RedisLocker($id);
}
}
abstract class AbstractLocker {
abstract public function __construct($id);
abstract public function lock();
abstract public function unlock();
abstract public function isLocked();
}
class RedisLocker extends AbstractLocker {
/// Key prefix
const PREFIX = 'lock/';
/// @var \Redis
private static $redis;
/// @var string DB item key
private $key;
/// @var int Expiration time in seconds
private $expire = 86400;
/**
* @param mixed $id ID of a job or group of jobs
*/
public function __construct($id) {
if (!static::$redis) {
static::$redis = Factory::redis();
}
$this->key = static::PREFIX . '/' . $id;
}
public function lock() {
$this->_fixDeadlocks();
$r = static::$redis;
// Set the key to the current process ID
// within a transaction (see http://redis.io/topics/transactions).
$r->multi();
$result = $r->setnx($this->key, getmypid());
$r->setTimeout($this->key, $this->expire);
$r->exec();
return (bool) $result;
}
public function unlock() {
$r = static::$redis;
// Delete the key from DB within a transaction.
$r->multi();
$result = $r->delete($this->key);
$r->exec();
return (bool) $result;
}
public function isLocked() {
$this->_fixDeadlocks();
return (bool) static::$redis->exists($this->key);
}
private function _fixDeadlocks() {
$r = static::$redis;
if (!$r->exists($this->key) || (!$pid = $r->get($this->key))) {
return;
}
$running = (bool) posix_kill($pid, 0);
if ($pid && $running) {
// Another process is running normally
return;
}
if (!$running) {
// Process is not running, so the keys must not exist
if ($r->exists($this->key) && $pid == $r->get($this->key)) {
// Deadlock found
$this->unlock();
}
}
}
}
//////////////////////////////////////////////////////////////////
// Usage
$id = 'Bubbles';
$locker = Factory::locker($id);
if ($locker->isLocked()) {
trigger_error("$id job is locked");
exit(1);
}
$locker->lock();
for ($i = 0; $i < 10; ++$i) { echo '. o O '; usleep(1e6); }
echo PHP_EOL;
$locker->unlock();
$ php script.php
. o O . o O . o O . o O . o O . o
$ php script.php
Notice: Bubbles job is locked in /home/ruslan/tmp/script.php on line 121
shell> cat /root/run_sleep.sh
#!/bin/bash
sleep 10000
shell> crontab -l
* * * * * sh /root/run_sleep.sh
ps
没有,对脚本的每个调用都独立于其他呼叫,但是您应该考虑到脚本每次数据库同时运行时,数据库将被超载...建议至少每两分钟运行脚本(*/2)
像Pepo一样说话。这打开了一个新的过程。某些情况可能是一个问题。为了解决这个问题,您可以像Laravel一样使用Jobqueue。或者,您可以创建一个更好的任务列表,以与您的Aplication过程相似,类似于Jobqueue,有些喜欢具有列表的表或文件来处理操作/功能,以及对项目待定/处理/处理的状态。 有了多个进程的问题,请在进程之前检查您的数据。