简单的PHP缓存会创建太多文件 - 需要子文件夹

时间:2016-04-27 10:06:17

标签: php caching substring

我正在使用我之前在堆栈溢出时找到的脚本来缓存我的动态php页面,我对这个简单的解决方案非常满意,因为它只是工作而且我能够将它与我的基本知识集成:D它只是PHP代码而不使用.htaccess

创建URL的MD5哈希值以为缓存文件创建唯一名称。但是,现在我的文件夹中有很多文件(大约300.000),在通过ftp关于加载时间打开文件夹时等待很烦人。为了减少一个文件夹中的文件数量,我正在寻找一个解决方案,使用前两个字母作为子文件夹的名称。

目前的工作原理:

  • 网址:e72b0f58601e6d0c12f71a40b14101b7
  • 文件:cache / e72b0f58601e6d0c12f71a40b14101b7.html

希望解决方案:

  • 网址:e72b0f58601e6d0c12f71a40b14101b7
  • 文件:cache / e7 / e72b0f58601e6d0c12f71a40b14101b7.html

如果子文件夹不存在,则应自动创建它们。有人能够帮我解决这个问题吗?或者对此解决方案有任何担忧吗?

考虑使用substr-command,但我的“实验”效果不佳。

提前致谢!

更新:感谢回复,我能够成功编辑代码。所需的更改可以在原始代码

下找到

我用于缓存的代码(来源:stackflow / http://www.sanwebe.com/2013/09/php-cache-dynamic-pages-speed-up-load-times/

<?php
//settings
$cache_ext  = '.html'; //file extension
$cache_time     = 3600;  //Cache file expires afere these seconds (1 hour = 3600 sec)
$cache_folder   = 'cache/'; //folder to store Cache files
$ignore_pages   = array('', '');

$dynamic_url    = 'http://'.$_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] . $_SERVER['QUERY_STRING']; // requested dynamic page (full url)
$cache_file     = $cache_folder.md5($dynamic_url).$cache_ext; // construct a cache file
$ignore = (in_array($dynamic_url,$ignore_pages))?true:false; //check if url is in ignore list

if (!$ignore && file_exists($cache_file) && time() - $cache_time < filemtime($cache_file)) { //check Cache exist and it's not expired.
    ob_start('ob_gzhandler'); //Turn on output buffering, "ob_gzhandler" for the compressed page with gzip.
    readfile($cache_file); //read Cache file
    echo '<!-- cached page - '.date('l jS \of F Y h:i:s A', filemtime($cache_file)).', Page : '.$dynamic_url.' -->';
    ob_end_flush(); //Flush and turn off output buffering
    exit(); //no need to proceed further, exit the flow.
}
//Turn on output buffering with gzip compression.
ob_start('ob_gzhandler'); 
######## Your Website Content Starts Below #########
?>
<!DOCTYPE html>
<html>
    <head>
        <title>Page to Cache</title>
    </head>
        <body>
            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer ut tellus libero.
        </body>
</html>
<?php
######## Your Website Content Ends here #########

if (!is_dir($cache_folder)) { //create a new folder if we need to
    mkdir($cache_folder);
}
if(!$ignore){
    $fp = fopen($cache_file, 'w');  //open file for writing
    fwrite($fp, ob_get_contents()); //write contents of the output buffer in Cache file
    fclose($fp); //Close file pointer
}
ob_end_flush(); //Flush and turn off output buffering

?>

如果您对该解决方案感兴趣,则需要更新这些行:

原件:

 $cache_folder   = 'cache/'; //folder to store Cache files
 $dynamic_url    = 'http://'.$_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] . $_SERVER['QUERY_STRING']; // requested dynamic page (full url)

已更新(动态网址相同,但由于订单顺序不同而在此处提及):

$dynamic_url    = 'http://'.$_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] . $_SERVER['QUERY_STRING']; // requested dynamic page (full url)
$cache_folder   = 'cache/'.substr(md5($dynamic_url),0,2).'/'; //folder to store Cache files

...

原件:

if (!is_dir($cache_folder)) { //create a new folder if we need to
mkdir($cache_folder);
}

更新:

if (!is_dir($cache_folder)) { //create a new folder if we need to
mkdir($cache_folder, 0777, true);
}

3 个答案:

答案 0 :(得分:0)

而不是

$cache_file = $cache_folder.md5($dynamic_url).$cache_ext; // construct a cache file
...
if (!is_dir($cache_folder)) { //create a new folder recuirsively if we need to
    mkdir($cache_folder);
}

使用

$cache_folder .= substr(md5($dynamic_url),0,2) . '/';
$cache_file = $cache_folder.md5($dynamic_url).$cache_ext;
...
if (!is_dir($cache_folder)) { //create a new folder if we need to
        mkdir($cache_folder, 0777, true);
}

这会将第一个文件名的字符添加为新的子文件夹,如果该文件夹不存在则递归创建该文件夹。

答案 1 :(得分:0)

  

在通过ftp关于加载时间打开文件夹时等待很烦人

我不知道FTP中的“打开文件夹”操作。当然,如果您要获取该文件夹的列表,则需要时间来传输数据,并在您的客户端进行渲染。它确实通过查看文件夹来解决你获得的问题。

可能更多的问题是在缓存中找到单个项目并确定驱逐候选者所需的时间 - 但这完全取决于数据所在的文件系统 - 而且您没有提供任何详细信息那些也不是这些过程的时间安排。

300,000是很多文件 - 它可能是正确的数字 - 再次你没有提供任何关于这是否是预期的指示。 OTOH可能会指出生成缓存键的方法存在问题,以及它是否适合您的应用程序。

要使用子文件夹,只需更改:

$cache_file = $cache_folder.md5($dynamic_url).$cache_ext;

$cache_file = $cache_folder.mk_hash_path($dynamic_url,$cache_folder).$cache_ext;
...

function mk_hash_path($dynamic_url,$cache_folder)
{
  md5($dynamic_url);
  $subfolders=4;
  while ($subfolders--) {
     $hash=substr($hash, -$subfolders, 1) . '/' . $hash;
  }
  if (!is_dir(dirname($cache_folder . $hash))) {
      mkdir(dirname($cache_folder . $hash,0777, true))
  }
  return $hash;
}

但更好的想法是使用缓存反向代理。

答案 2 :(得分:-1)

考虑使用其他缓存机制而不是文件缓存。

您应该使用redis或memcache作为缓存存储。对于整页缓存选择CDN解决方案。有像Cloudfront这样的免费CDN。