ホームページ >バックエンド開発 >PHPの問題 >flock php ロックが失敗した場合はどうすればよいですか?

flock php ロックが失敗した場合はどうすればよいですか?

藏色散人
藏色散人オリジナル
2021-11-08 09:32:402293ブラウズ

flock isRunning() メソッドの終了後に $file_lock が使用されなかったため、PHP ロックが失敗しました。解決策は、PHP ライフ サイクル全体でファイル ハンドルが解放されないようにすることです。

flock php ロックが失敗した場合はどうすればよいですか?

この記事の動作環境: Windows 7 システム、PHP バージョン 7.1、DELL G3 コンピューター

こんな場合はどうすればよいですか? PHP ロックが失敗しますか?

php flock エラーの問題の解決策:

過去 2 日間で、私はサイド プロジェクト用に PHP の同時実行を回避するメソッドを書きました。 crontab によってスケジュールされたスクリプト。

方法

通常、ファイル ロック flock メソッドを使用すると、同じ PHP スクリプトで同じディスク ファイルのノンブロッキング ロックが使用されます。が占有されている場合、エラーが報告されるため、スクリプトはすぐに終了できます。

現象

しかし実際には、コントローラー ファイル内で直接フロックできることがわかりました。フロック ロジックが他のファイルの関数にカプセル化されている場合、 失敗した。

原因

長い間デバッグを行った後、以前にこのピットに遭遇したことを突然思い出しました。 。

エラー コードは次のとおりです。

class Crontab
{
    /**
     * 确保任务没有并发执行
     */
    public static function isRunning() {
        global $argv;
        $ident = [];
        foreach ($argv as $idx => $value) {
            $ident[] = $idx . '=' . urlencode($value);
        }
        $ident = md5(implode('&', $ident));
        $lockDir = \Yii::getAlias('@app/runtime/crontab/');
        @mkdir($lockDir, 0755, true);
        $file_lock = fopen($lockDir . $ident, 'w+');
        $wouldBlock = 0;
        flock($file_lock, LOCK_EX | LOCK_NB, $wouldBlock);
        return $wouldBlock;
    }
}
class Crontab
{
    /**
     * 确保任务没有并发执行
     */
    public static function isRunning() {
        global $argv;
 
        $ident = [];
        foreach ($argv as $idx => $value) {
            $ident[] = $idx . '=' . urlencode($value);
        }
        $ident = md5(implode('&', $ident));
 
        $lockDir = \Yii::getAlias('@app/runtime/crontab/');
 
        @mkdir($lockDir, 0755, true);
 
        $file_lock = fopen($lockDir . $ident, 'w+');
 
        $wouldBlock = 0;
        flock($file_lock, LOCK_EX | LOCK_NB, $wouldBlock);
 
        return $wouldBlock;
    }
}

コマンド ライン パラメーターに基づいて、PHP タスクを表す一意のハッシュ値を生成します。

ロック ファイルを作成し、flock ノンブロッキング ロックを実行し、willBlock を返してロックが占有されているかどうかを識別します。

スクリプト エントリで Crontab::isRunning() メソッドを呼び出したところ、スクリプトを同時に開始した後は常にロックを取得できることがわかりました。

エラーの理由は次のとおりです: isRunning() メソッドが終了した後、$file_lock は引き続き使用されず、PHP によってガベージ コレクションが行われます。$fp ファイル ハンドルが閉じられ、ロックが自動的に行われます。解放されました。

解決策

class Crontab
{
    /**
     * 保存起来避免被php作为垃圾回收
     * @var null
     */
    static $file_lock = null;
    /**
     * 确保任务没有并发执行
     */
    public static function isRunning() {
        global $argv;
        $ident = [];
        foreach ($argv as $idx => $value) {
            $ident[] = $idx . '=' . urlencode($value);
        }
        $ident = md5(implode('&', $ident));
        $lockDir = \Yii::getAlias('@app/runtime/crontab/');
        @mkdir($lockDir, 0755, true);
        self::$file_lock = fopen($lockDir . $ident, 'w+');
        $wouldBlock = 0;
        flock(self::$file_lock, LOCK_EX | LOCK_NB, $wouldBlock);
        return $wouldBlock;
    }
}
class Crontab
{
    /**
     * 保存起来避免被php作为垃圾回收
     * @var null
     */
    static $file_lock = null;
 
    /**
     * 确保任务没有并发执行
     */
    public static function isRunning() {
        global $argv;
 
        $ident = [];
        foreach ($argv as $idx => $value) {
            $ident[] = $idx . '=' . urlencode($value);
        }
        $ident = md5(implode('&', $ident));
 
        $lockDir = \Yii::getAlias('@app/runtime/crontab/');
 
        @mkdir($lockDir, 0755, true);
 
        self::$file_lock = fopen($lockDir . $ident, 'w+');
 
        $wouldBlock = 0;
        flock(self::$file_lock, LOCK_EX | LOCK_NB, $wouldBlock);
 
        return $wouldBlock;
    }
}

ファイル ハンドルは PHP ライフ サイクル全体を通じて解放されず、クラスの静的メンバー変数に保存されるようにしてください。

推奨学習: 「PHP ビデオ チュートリアル

以上がflock php ロックが失敗した場合はどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。