HI
由于我使用的是共享主机软件包,并且我无法使用PECL Memcache,我会很感激使用我自己的小缓存系统或使用PEAR Cache_Lite系统时我自己有些疑问。
所以这是我的功能:
<?php
//this one create a simple .txt file named by unique query_key string generated width e.g $file_name=md5("SELECT * FROM table"); content of that file is serialized value of mysql return
function write($query_key,$result)
{
global $config;
$new_file_name=md5($query_key);
$result_to_write=serialize($result);
if($handle=opendir($config['cache_dir']))
{
$f=fopen($config['cache_dir'].$new_file_name.'.txt','w+');
fwrite($f,$result_to_write);
fclose($f);
closedir($handle);
}
}
// this one reads content of file (serialized mysql return of unique query_key) if timeout hes not expired, and if it is it return false
function read($query_key,$timeout)
{
global $config;
$file_name=md5($query_key);
if($handle=opendir($config['cache_dir']))
{
if(file_exists($config['cache_dir'].$file_name.'.txt'))
{
$last_accessed=filemtime($config['cache_dir'].$file_name.'.txt');
$now=time();
if(($now-$last_accessed)<$timeout)
{
$file=fopen($config['cache_dir'].$file_name.'.txt','rb');
$f=fread($file,filesize($config['cache_dir'].$file_name.'.txt'));
$array=unserialize($f);
fclose($file);
closedir($handle);
}else{ return FALSE; }
}else{ return FALSE; }
}
if(!empty($array)) return $array;
else return FALSE;
}
//and finally this one which is used when executing query, so it has timeout in seconds, if file (cached result) exists, and timeout has not expired, it returnt cached data , or it reads from database returns new result,and cache new result by writing new file
function cache($query)
{
$timeout=600;
$file_exists=read($query,$timeout);
if($file_exists)
{
return $file_exists;
}else{
$result=get_rows($query);
write($query,$result);
return $result;
}
}
?>
这个我的小“缓存系统”工作得非常好,正如我所看到的,PEAR Cache_Lite的工作方式几乎相同,而且由于我不熟悉梨缓存系统,我想知道哪些更好,更安全,在这两者之间使用更快的解决方案,以及为什么??
Thanx很多!!
答案 0 :(得分:4)
就个人而言,我会使用一个库。编写缓存层似乎要困难得多。你不能做到这一点并不困难,但是很难将所有边缘情况和怪癖都赶出系统。你可以使用类似Cache_Lite的东西,但我会建议一个更好的缓存层。其中有一些(独立和框架出生)。以下是一些:
Zend_Cache - 您可以单独使用此功能。但它也经过精心设计和测试......
Cache_Lite - 如果您只想要文件缓存。它重量轻,但也不是非常灵活(但可能是你想要的)。
Kohana's cache。它相当灵活,但我不太确定与框架的其他部分分开是多么容易(没有经验)。
关于您的代码的一些评论:
我会使用不同的变量名。 $file_exists
函数中的cache()
是一个非常糟糕的名称。它应该是$cache_results
之类的东西。使用语义来识别您的名字。
我真的将它包装在一个类中,这样你就可以更好地进行初始化。根据请求,您只需要执行一些操作,因此无需每次都执行此操作(稍等一些)。
清除您的统计信息缓存!每次请求运行clearstatcache()
一次。原因是PHP可以缓存无效的统计信息并返回file_exists
,filemtime
等错误信息。但它相当昂贵,所以我不会每次请求多次运行它... < / p>
opendir
或read()
完全不需要使用write()
。如果要验证该目录是否存在,只需调用is_dir($dir)
即可。现在,你正在打开一个手柄,什么都不做。
read()
和write()
都有资源泄漏,其中有路径可以打开目录但不关闭目录。虽然这在大多数情况下都不是一件大事,但要正确关闭资源。 (更好的是,完全消除呼叫)。
请勿将fopen(); fwrite(); fclose();
用于此类操作。如果您在写入文件时出现另一个请求(这将导致部分读取),您可能会自己开枪。相反,使用file_put_contents($filename, $data, LOCK_EX);
进行写作。它基本上是原子的(不完全,但足够接近你的目的)。我会在read()
:
$file=fopen($config['cache_dir'].$file_name.'.txt','rb');
if (flock($file, LOCK_SH)) {
$f=fread($file,filesize($config['cache_dir'].$file_name.'.txt'));
flock($file, LOCK_UN);
}