短篇小说:
我有一个名为(cron_mailings.php
)的脚本,我需要知道它是否正在运行。是否有函数或变量如$ _SERVER来获取当前脚本(cron_mailings.php
)的实例数?
因为我不希望脚本在任何给定时刻运行多次。
长篇故事:
我们有cron job
调用脚本列表,其中一个脚本是(cron_mailings.php
)。
cron_mailings.php
转到mailings
表,获取电子邮件记录列表 - 首先是100 - 然后从表中发送和删除它们。稍后,cron job
将再次执行,并致电cron_mailings.php
,以处理接下来的100封电子邮件。
问题是,有人错误地设置了cron作业,上周它在5秒内运行了6次并且我们有一个典型的Race Condition,第一个实例获得了前100个用户,而它正在处理用户#10的另一个实例cron job
调用了相同的脚本,cron_mailings
运行并获取了100个用户。现在,两个脚本都与90个用户重叠,这些用户两次收到同一封邮件。
我们已经修复了cron工作,但以防我必须找到解决方案,因为我不知道将来会使用该脚本,所以
我实施了两个解决方案:
将字段标志添加到名为mailings
的db is_fetched
表中(1表示已取,0
除此以外)。并设置cron_mailings.php以仅获取标记的记录
with is_fetched = 0。通过该解决方案不止一次的实例
scrip实际上可以在表的不同部分运行和工作
。例如。 first instance调用前100条记录并将1分配给
is_fetched,另一个实例将来到第二个100
记录其中is_fetched = 0并处理它们。
通过在db表中放置一个标志以了解脚本是否正在运行来阻止整个脚本,然后在脚本顶部执行以下操作:
check if (is_cron_maillings_running() === 'Y')
{
die("script is running at the moment");
}
else
{
set_is_cron_maillings_running("Y");
// do some stuff - send emails and save the world
//1
//.
//.
//10
set_is_cron_maillings_running("N");
}
两种解决方案都很好(基本上第二种解决方案会胜过第一种解决方案)
但我有一个问题:
如果在到达最后一行set_is_cron_maillings_running("N");
之前脚本在步骤1和10之间死亡/崩溃/错误抛出/ db服务器消失/ .etc怎么办?
cron作业调用的任何其他脚本将在db表中看到is_cron_maillings_running = Y并且永远不会再次执行,除非有人手动将值重新分配给N.
对于找到更好的锁定脚本方法的建议,我非常开放。到目前为止,在我看来,我认为如果我设法从服务器获取运行脚本列表(搜索当前脚本是否正在运行),这比为db表无法真正完全执行的db表分配值更安全并且分配正在运行= N.
答案 0 :(得分:1)
不是在锁定文件/字段中存储Y / N,而是在设置锁定时存储日期(Y),或者在没有锁定(N)时存储空值。然后,如果该日期超过X时间量,请忽略它。这样一旦出现问题,一旦锁定失效,您的脚本将再次开始工作。