对于我的网站,我让Cron Jobs每30分钟运行一次,如果我试图在这30分钟内访问我的网站,我要么得到一个500 Internal Server错误,要么得到网站上任何页面的5-10秒的加载时间。
我使用的是Php,我的cron作业使用的是Php和MySQL。
我怎样才能让它不会落后于我的整个网站,或者让它变得更快,这样滞后就会更少?
Crons:

每15分钟运行一次的cron之一:
<?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();
}
?>我如何才能使这些延迟更少或根本不延迟?
发布于 2012-09-18 07:21:09
第一个建议是将prepare调用移出循环。更新将锁定您的表一段时间,因此仅在完成操作后才更新...在数组中缓存需要更新的内容,并启动一个事务,执行所有更新而不是提交。更新了邮件脚本的代码示例
<?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)语句之后
发布于 2012-09-18 00:40:12
编写更高效的脚本或获得更好的硬件。
编辑:
在大量发送电子邮件方面,您可以向脚本添加超时,这样它就不会尽可能快地处理所有电子邮件。这将减少CPU上的负载,但会使脚本占用更长的时间。
例如:
for(all emails)
{
//send email
sleep(5);
}https://stackoverflow.com/questions/12463614
复制相似问题