如何阻止并发PHP脚本同时执行相同的代码?

时间:2014-01-17 11:02:17

标签: php wordpress curl concurrency

我正在使用货币汇率服务,每月只允许1000个请求,所以我必须将检索到的汇率保存到数据库一小时,然后再用新请求更新。

然而,我的网站一直在要求新的汇率远远超过每小时,我终于意识到这是因为并发的PHP脚本试图同时更新数据库的速率。以下是我的代码的简化示例:

function get_rates()
{
    $rates = get_transient( 'exchange_rates' );
    if( $rates === false ) {

        $ch = curl_init( 'http://examplecurrencyrates.com/rates.json' );
        curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
        $rates = curl_exec( $ch );

        $cache_time = 3600; // 60 mins
        set_transient( 'exchange_rates', $rates, $cache_time );

        curl_close( $ch );
    }
    return $rates
}

如何确保每小时只有一个请求来更新汇率?

3 个答案:

答案 0 :(得分:3)

我建议使用cronjobs(或任何其他作业调度程序),它将通过每小时运行一次脚本来更新费率。 你每个月有720个小时,所以你不会超过每月1000个限制。

答案 1 :(得分:1)

我使用的一种方法,在类似但略有不同的情况下是锁定文件。

在我的例子中,我有一个每分钟都运行的脚本。如果这个脚本在某个运行中有很多处理要做,那么可能需要3分钟 - 在这段时间里我不希望这个脚本的另外2个实例运行并尝试执行相同的工作。

所以我所做的就是在流程开始时创建一个锁文件,例如:

$lock_file = fopen('/lock_file_directory/my_script.lock', 'w');
fclose($lock_file);

在脚本结束时,后期处理,我添加以下内容:

unlink('/lock_file_directory/my_script.lock');

这样,在处理脚本期间,锁文件始终存在。

现在,为了使这项工作,在脚本的开头 - 添加:

if(file_exists('/lock_file_directory/my_script.lock')) { exit; }

这意味着如果锁定文件存在,则下一个实例将不会运行。

答案 2 :(得分:0)

您应该使用像

这样的MySQL表
CREATE TABLE IF NOT EXISTS `running` (
  `script` varchar(255) NOT NULL,
  PRIMARY KEY (`script`)
) ENGINE=InnoDB; 

在启动脚本中尝试此查询

INSERT INTO running ('myscript');

如果有任何已经运行它第二次死亡

在脚本末尾执行

DELETE FROM running WHERE script = 'myscript' LIMIT 1;