<?php
namespace App\Tools;
use Log;
use Exception;
//command 文件鎖 command執行完畢會釋放
class CmdLock
{
public function __construct($called_class)
{
$lanmao_lock_path = sys_get_temp_dir() . '/lanmao_lock';
if (!is_dir($lanmao_lock_path)) {
mkdir($lanmao_lock_path);
}
$this->called_class = $called_class;
$class_info = explode('\\', $called_class);
$this->class = end($class_info);
$this->lockname = $this->class . '.lock';
$this->lock_path = $lanmao_lock_path . '/';
$this->lock_realpath = $this->lock_path . $this->lockname;
$this->lock = fopen($this->lock_realpath, 'w+');
}
public function lock()
{
$date = date("Ymd H:i:s", time(null));
$msg = "command: {$this->class} ========> 準備加鎖";
Log::info($msg);
if (flock($this->lock, LOCK_EX | LOCK_NB)) {
Log::info("command: {$this->class} ========> 鎖定...");
return true;
}
throw new Exception('加鎖失敗! ===> ' . $this->called_class);
}
public function unlock()
{
$msg = "command: {$this->class} ========> 準備釋放鎖";
Log::info($msg);
flock($this->lock, LOCK_UN);
fclose($this->lock);
}
}
(執行腳本前需要創建 相應的lock文件 利用flock 對已經存在的文件進行鎖控制)
以前加鎖做法是 通過創建 一個 xxx.lock文件 確認加鎖 執行完畢 刪除xxx.lock
這種做法有個弊端就是,併發的情況下,如果程序拋出異常 會導致lock一直掛在那 無法解鎖
現在的加鎖方案是 利用linux flock 加鎖機制 可以考慮 阻塞 和非阻塞的模式 。即使拋異常 也不影響 下次執行。