Я создал простой веб-сайт php с базами данных. Теперь я пытаюсь реализовать некоторое простое кэширование на сайте. я попробовал это откуда-то
<?php $reqfilename="test"; $cachetime = 60*5; // 5 minutes $cachefile = "cache/".$reqfilename.".html"; $cf2="cache/".$reqfilename."2.html"; if (file_exists($cachefile) && ((time() - $cachetime) < filemtime($cachefile))) { include($cachefile); exit; } ob_start(); ?> CONTENT OF THE PAGE GOES HERE <?php $fp = @fopen($cf2, 'w'); if($fp){ fwrite($fp, ob_get_contents()); fclose($fp); rename($cf2,$cachefile); } ob_end_flush(); ?>
Но что делать, если файл кэша переименовывается и кто-то запрашивает страницу. Будет ли отображаться ошибка или просто пользователь задержит задержку?
Чтобы уменьшить время только изменения файла кэша, я использую переименование вместо прямой записи в исходный файл кеша
Правильный код для этого (на основе ответа на webbiedave ниже)
<?php $reqfilename="test"; $cachetime = 60*5; // 5 minutes $cachefile = "cache/".$reqfilename.".html"; if (file_exists($cachefile) && ((time() - $cachetime) < filemtime($cachefile))) { include($cachefile); exit; } ob_start(); ?> CONTENT OF THE PAGE GOES HERE <?php $fp = @fopen($cachefile, 'w'); if (flock($fp, LOCK_EX | LOCK_NB)) { fwrite($fp, ob_get_contents()); flock($fp, LOCK_UN); fclose($fp); } ob_end_flush(); ?>
Переименование файла не является источником вашей проблемы. Основным условием гонки с вашим сценарием является несколько запросов, определяющих истекшее время mtime и все записи в test2.html
.
Лучшим подходом является выполнение исключительной, неблокирующей стаи (предполагающей не-окна) сразу же после обнаружения истечения mtime, буфера вывода, перезаписывания файла и освобождения блокировки. Если flock
возвращает false, другой процесс записывается в него, и текущий процесс должен полностью пропустить запись.
Если во время блокировки выполняется запрос, веб-сервер будет ожидать завершения записи файла (и блокировки), а затем обслуживать файл.
Я не думаю, что ваш источник будет работать должным образом, потому что вы не удаляете кеш-файл