我做了一个简单的数据库驱动的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(); ?>
答案 0 :(得分:1)
重命名文件不是问题的根源。您的脚本的主要竞争条件是多个请求检测到过期的mtime并且所有写入test2.html
。
更好的方法是在检测到过期的mtime后立即执行独占的非阻塞flock(假设为非窗口),缓冲输出,覆盖文件并释放锁定。如果flock
返回false,则另一个进程正在写入它,当前进程应该完全跳过写入。
如果在锁定期间发出请求,Web服务器将等待文件写入完成(并释放锁定),然后提供文件。
答案 1 :(得分:0)
我认为您的源代码无法正常运行,因为您没有删除缓存文件