我正在使用货币汇率服务,每月只允许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
}
如何确保每小时只有一个请求来更新汇率?
答案 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;