我有一个小问题,希望有人可以了解情况。
情况:
我有一个内置于PHP CMS中的自定义部分缓存机制。简而言之,当处理CMS中的模板时,它处理'cachable'PHP代码并且不处理'不可缓存的'php代码,然后将生成的代码保存为要处理的文件以供将来访问页。
问题:
当系统“查找”缓存文件时,我遇到文件访问延迟。使用GLOB查找匹配文件的250,000个缓存文件在网站上没有流量时需要1/4秒 - 有时流量峰值为10-15秒。几乎看起来两个单独的客户端会话不能同时运行GLOB,因此它们瓶颈。
我在寻找什么:
...是一种替代方法,或提供块缓存的优化,没有瓶颈问题。必须考虑我的独特顾虑(概述如下)。我需要一种更快的方式来访问这些文件或另一个部分页面缓存方向:/
============================================== < / p>
ABRIDGED CODE:
// var to hold cached page path, if found
$pageCache = NULL;
// get the URL for current page
// there is actually some other code here that could alter the 'theURL4Cache' var for various reasons, but for simplicity in this example lets just keep it the REQUEST_URI
$GLOBALS['theURL4Cache'] = $_SERVER['REQUEST_URI'];
// check if existing cache file is in place
$filePattern = 'parsed/page_cache/*^' . $_SERVER['SERVER_PORT'] . '^' . $_SERVER['HTTP_HOST'] . '^' . (($_SESSION['isMobile']) ? 'M' : 'D') . '^L' . $language . '^T*^P' . $attributes['pageId'] . '^' . md5($GLOBALS['theURL4Cache']) . sha1($GLOBALS['theURL4Cache']) . '.php';
$fileArr = glob($filePattern);
// possible multiple files found that fit / expired files found that fit the pattern
// lets grab the newest file and try to use it
if(count($fileArr)){
rsort($fileArr);
$file = $fileArr[0]; // get file with latest expire date
if($file > 'parsed/page_cache/' . date('Y-m-d-H-i-s')) $pageCache = $file; // set an attribute to hold the valid file path to the cached file
// remove files that are no longer corrent
for($i=(($pageCache === NULL) ? 0 : 1); $i<count($fileArr);$i++) unlink($fileArr[$i]);
};
if($pageCache){
// cached page is found, lets process and output this puppy
include($pageCache);
} else {
// cached page is not found, let's build a cacheable page from the CMS template
$newCode = // ..... various code is processed here to isolate the cacheable code blocks and process while leaving the non-cacheable blocks intact ..... //
// create the new file path where the cached code will be placed
// first we need an expiration date
$cacheDate = date_create();
date_add($cacheDate, date_interval_create_from_date_string( $cache_increment . ' ' . $cache_interval)); // $cache_increment and $cache_interval are stored in the CMS DB for each page, giving the content manager control over the expiration of the page in cache
$filePath = $GLOBALS['iProducts']['physicalRoot'] . "/parsed/page_cache/" . date_format($cacheDate,'Y-m-d-H-i-s') . "^" . $_SERVER['SERVER_PORT'] . '^' . $_SERVER['HTTP_HOST'] . '^' . (($_SESSION['isMobile']) ? 'M' : 'D') ."^L" . $language . "^T" . $templateId . "^P" . $attributes['pageId'] . "^" .md5($GLOBALS['theURL4Cache']) . sha1($GLOBALS['theURL4Cache']) . '.php'; // create the file path
if(file_exists($filePath)) unlink($filePath); // delete the file if it already exists
$fp = fopen($filePath,"w"); // create the new file
flock($fp,LOCK_EX);
fwrite($fp,$newCode); // write the cache file
flock($fp,LOCK_UN);
// now output this puppy
eval($newCode);
};
为什么你的文件是什么样的,你问的是什么?
嗯,我很高兴你问过! CMS的另一部分包括“智能缓存管理”,其中如果页面或模板被内容管理器修改,则所有缓存的页面都将从系统中清除。此外,页面中的内容可能会因URL查询字符串中的attribs而异,如果它是移动设备呈现,SSL与非SSL,域名或当前会话语言(引擎支持多种语言内容)与同一页面相关联,根据会话语言有条件地输出。
所以这是一个缓存的页面文件名示例: 2014-02-14-10-36-36 ^ 80 ^ www.mydomain.com ^ M ^ L ^ T42 ^ P41 ^ a067036ef358f12a0049740f035a7ee688dbb0033c19a70163d6c453dbc5b84f1889ffe2.php
以下是文件名的组成部分: 到期最新^端口^域^ mobileOrDesktop ^语言^模板^页^ MD5 + sha1OfURL.php
以下是解释的组件:
欢迎任何想法或建议。提前谢谢!
答案 0 :(得分:0)
一些想法:
您可能需要考虑内存缓存系统,例如memcached或redis,而不是磁盘上的缓存系统。读取和写入磁盘的负载可能很大。
有模板引擎(如SMARTY http://www.smarty.net/)会为你做很多繁重的工作。
您应该使用一致的哈希规则来保存文件名,然后使用标记的二级哈希值,而不是使用globs来搜索目录。例如,保存所有文件:
$fname = sha1($GLOBALS['theURL4Cache'].ALL_THE_REST_OF_THOSE_VARIABLES);
$cachedir1 = substr($fname ,0,1);
$cachedir2 = substr($fname,0,2);
$finalname = 'parsed/page_cache/' . $cachedir1 . '/' .$cachedir2 .'/'. $fname . '.php';
这意味着一个sha1为abcdefgh的文件将保存为'parsed / page_cache / a / ab / abcdefgh.php'。这有助于减少文件系统性能下降。
现在,只要您知道文件名,就能找到该文件 - 基本上您将目录路径用作大型哈希表。对于您的标签,设置另一组哈希 - 这些哈希可以保存为磁盘或数据库或内存中的文件。每当将页面添加到其中一个标记时,请将sha1摘要或文件名添加到相应的哈希中。例如,在一个名为'parseHashes / is_mobile.php'的文件中,你可以有一个像
这样的数组$arr = array(
"abcd",
"defg"
);
每个键都是您需要查找和/或删除的sha1摘要。当您需要操作标记中的文件集时,您可以迭代存储的sha摘要,并且您知道在哪里可以找到文件内容。
所有这一切,您应该真正研究基于内存或甚至数据库的解决方案。在filesytem上执行此操作需要做很多工作,并且不能很好地扩展。