【问题标题】:Cron Jobs lag my website while they run [closed]Cron Jobs 在运行时落后于我的网站 [关闭]
【发布时间】:2012-09-18 07:41:56
【问题描述】:

对于我的网站,我每 30 分钟运行一次 Cron 作业,如果我尝试在这 30 分钟标记访问我的网站,我会收到 500 内部服务器错误,或者我会收到 5-10 秒的任何页面加载时间地点。

我正在使用 Php,而我的 cron 作业正在使用 Php 和 MySQL。

我怎样才能让它不落后于我的整个网站或让它更快,从而减少滞后?

Cron:

每 15 分钟运行一次的 crons 之一:

<?php
require('functions.php');

global $mysqli;

$select = $mysqli->prepare("SELECT `tkn` FROM `users` ORDER BY `dt` ASC LIMIT 0, 200");
$select->execute();
$select->bind_result($cur_token);

$tokens = array();

while($select->fetch())
{
    array_push($tokens, $cur_token);
}

foreach($tokens as $token)
{
    $api = Class::Instance($token);
    $info = $api->Users->Info();

    if(empty($info->error))
    {
        $info->data->token = $token;
        updateUser($info->data);

    } else if($info->error->code == 400) {
        $update = $mysqli->prepare("UPDATE `users` SET `active` = 0 WHERE `tkn` = ?");
        $update->bind_param('s', $token);
        $update->execute();
    }
}

?>

其他 Cron 作业:

<?php
require('functions.php');

global $mysqli;

$select = $mysqli->prepare("SELECT `email`, `username`, `id` FROM `users` WHERE `email` IS NOT NULL AND `email` <> '' AND `credits` < `credits_offered` AND `emailed_credits` = 0");
$select->execute();
$select->bind_result($email, $username, $id);

$users = array();

while($select->fetch())
{
    $users[] = array("id" => $id, "email" => $email, "username" => $username);
}

foreach($users as $user)
{
    $to      = $user['email'];
    $subject = '';
    $message = "";
    $headers = 'From: email@domain.com' . "\r\n" .
        'Reply-To: reply@domain.com';

    mail($to, $subject, $message, $headers);

    $update = $mysqli->prepare("UPDATE `users` SET `emailed` = 1 WHERE `id` = ?");
    $update->bind_param('i', &$user['id']);

    $update->execute();
    $update->close();
}


?>

我怎样才能减少这些滞后或根本不滞后?

【问题讨论】:

  • 在没有任何进一步信息的情况下,您真的希望得到任何有用的答案吗?
  • 如果您说出 cronjobs 的作用可能会有所帮助....
  • cron 作业在做什么?他们跑了多长时间?他们是否使用会话在您的网站上执行任何 http 请求?这些作业是否锁定了站点其余部分所需的任何资源?如果没有更多细节,您的问题将无法回答
  • 同上,请编辑您的 cron 列表和您怀疑滞后的那些脚本的内容
  • Cron Jobs - 多少?请将您的 crontab 添加到问题中,如果它调用脚本,还有这些脚本。此外,您还可以在那段时间执行一些指标并记录负载和 i/o,这样实际上在这些高峰时服务器的压力会更加明显。 $ vmstat 1 - 因为你有不止一个,如果你已经知道它们很慢,不要同时启动它们。与其一次全部 50 个用户,不如每分钟做两个用户,而不是在 30 分钟内做 60 个用户。

标签: php mysql cron


【解决方案1】:

第一个建议是将准备调用移出循环。更新将锁定您的表一段时间,因此仅在完成操作后才更新...将需要更新的内容缓存在数组中并启动事务,执行所有更新而不是提交。 更新了邮件脚本的代码示例

<?php
require('functions.php');

global $mysqli;

$select = $mysqli->prepare("SELECT `email`, `username`, `id` FROM `users` WHERE `email` IS NOT NULL AND `email` <> '' AND `credits` < `credits_offered` AND `emailed_credits` = 0");
$select->execute();
$select->bind_result($email, $username, $id);

$users = array();

while($select->fetch())
{
    $users[] = array("id" => $id, "email" => $email, "username" => $username);
}

$u = array();

foreach($users as $user)
{
    $to      = $user['email'];
    $subject = '';
    $message = "";
    $headers = 'From: email@domain.com' . "\r\n" .
        'Reply-To: reply@domain.com';

    mail($to, $subject, $message, $headers);
    $u[] = $user['id'];

}
$update = $mysqli->prepare("UPDATE `users` SET `emailed` = 1 WHERE `id` = ?");
$update->bind_param('i', &$i);
$mysqli->autocommit(false);
foreach($u as $i)
    $update->execute();
$update->close();
$mysqli->commit();

哦,差点忘了,大多数mysql存储引擎都很笨,确保你使用InnoDB,那个有事务支持。或者,如果您使用“愚蠢”的存储引擎,如果您的 users.id 是 int ,您仍然可以欺骗它进行单个事务来更新多行

$update = $mysqli->prepare('UPDATE users SET emailed=1 WHERE id IN (' . implode(',', $u) . ')');
$update->execute();
$update->close();

改为关闭foreach($users as $user) 语句后

【讨论】:

  • 为什么?最后的循环外与循环内有区别吗?抱歉,我看不出在性能方面会有什么不同。 @xception
  • 查看我编写的代码,我执行一个事务,在其中更新所有需要更新的行,这就是为什么它应该更快,制作数据库副本,注释邮件调用不如果您不相信我,向人们发送垃圾邮件并对您的版本进行基准测试并在复制的数据库中的完全相同的数据集上挖掘,请记住在每次测试后重新加载数据
  • 我使用 Inno 因为外键。我将测试答案并在 10 分钟内报告我的结果。 @xception
  • 我的版本旧代码:0.1238 秒新代码(你的答案):0.0486 秒我印象深刻,它减少了一半。但我仍然需要修复另一个 cron 工作! @xception
  • 我将把它作为练习留给您,如果您在更改两个脚本后在 30 分钟标记处仍然遇到问题,请告诉我。
【解决方案2】:

编写更高效的脚本或获得更好的硬件。

编辑:

就群发电子邮件而言,您可以在脚本中添加超时,这样它就不会尽快处理所有电子邮件。这将减少 CPU 的负载,但会使您的脚本花费更长的时间。

例如:

for(all emails)
{
   //send email
   sleep(5);
}

【讨论】:

  • 这不是答案。最多是个坏评论。
  • @MarcB 诚然有点刻薄,但没有更多信息,这些是唯一可用的答案。如果他发布代码,我会很乐意尝试帮助提高脚本的效率。
  • 然后把它作为评论。一旦你得到信息,然后写一个答案
  • 嗨@thatidiotguy 我已经更新了我的问题。
猜你喜欢
  • 2017-06-29
  • 1970-01-01
  • 2014-08-19
  • 1970-01-01
  • 2019-05-07
  • 2011-08-15
  • 2015-01-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多