#php
#php
Вопрос:
Вот мой код:
$cachefile = "cache/ttcache.php";
if(file_exists($cachefile) amp;amp; ((time() - filemtime($cachefile)) < 900))
{
include($cachefile);
}
else
{
ob_start();
/*resource-intensive loop that outputs
a listing of the top tags used on the website*/
$fp = fopen($cachefile, 'w');
fwrite($fp, ob_get_contents());
fflush($fp);
fclose($fp);
ob_end_flush();
}
На первый взгляд казалось, что этот код работает нормально, но я обнаружил ошибку и не могу понять, как ее решить. В принципе, кажется, что после того, как я оставляю страницу в покое на некоторое время, файл кэша очищается (либо это, либо когда я обновляю страницу, он очищает файл кэша, делая его пустым). Затем условие видит теперь пустой файл кэша, определяет его возраст менее 900 секунд и извлекает содержимое пустого файла кэша вместо повторного запуска цикла и повторного заполнения кэша.
Я запустил файл кэша в командной строке и увидел, что он действительно пуст, когда существует эта проблема.
Я попытался установить значение 60 секунд, чтобы чаще повторять эту проблему и, надеюсь, разобраться в ней, но, похоже, она не повторяется, если я ее ищу, только когда я покидаю страницу и возвращаюсь через некоторое время.
Любая помощь?
Комментарии:
1. Вы уверены, что это не фатальная ошибка, которая возникает при повторном рендеринге страницы и скрывается под текущим
error_reporting()
?2. Добавьте фиктивную строку в начало вашего кэша, например
'<!--'.time().'-->'
, чтобы проверить, что в данный момент сохранено в файле.3. Привет, очевидно, вы урезали ненужный код (спасибо!), правильный ли порядок, который мы видим здесь? В частности, то, что вы не открывали файл с помощью fopen () до окончания ресурсоемкой части. В нынешнем виде file_put_contents(), казалось бы, гораздо более простой способ записи в файл.
4. Я думаю, что исправлением этого было бы убедиться, что файл не пустой перед чтением, как я могу это сделать?
5. Попробуйте заблокировать файл перед записью в него. Возможно, существует конфликт из-за нескольких выполняемых скриптов, пытающихся выполнить запись в один и тот же файл.
Ответ №1:
В процедурах кэширования, которые я пишу, я почти всегда проверяю размер файла, поскольку я хочу убедиться, что я не выдаю пустые данные, потому что я полагаюсь на скрипт bash для очистки кэша.
if(file_exists($cachefile) amp;amp; (filesize($cachefile) > 1024) amp;amp; ((time() - filemtime($cachefile)) < 900))
Это предполагает, что ваш выводимый файл кэша имеет размер > 1024 байт, что обычно так и будет, если это что-то относительно большое. Добавление файла блокировки также было бы полезно, как отмечено в комментариях выше, чтобы избежать попыток нескольких процессов выполнить запись в один и тот же файл блокировки.
Ответ №2:
вы можете дважды проверить размер файла с помощью функции filesize (), если он слишком мал, действуйте так, как если бы кэш был старым.
если в файле нет PHP, вы можете либо использовать readfile() из соображений производительности, либо просто отправить файл обратно конечному пользователю.