dev*_*ect 2 php pear memcached
你好。
由于我使用的是共享托管包,并且无法使用 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;
}
}
?>
Run Code Online (Sandbox Code Playgroud)
这个我的小“缓存系统”工作得很好,正如我所看到的,PEAR Cache_Lite 的工作方式几乎相同,而且由于我不熟悉 pear 缓存系统,我想知道什么是更好、更安全、更快的解决方案在这两者之间使用,为什么?
非常感谢!!
就个人而言,我会为此使用一个库。编写缓存层看起来要困难得多。不是难到你做不到,但很难把所有的边缘情况和怪癖都排除在系统之外。您可以使用 Cache_Lite 之类的东西,但我建议使用更好的缓存层。其中有一些(独立的和框架出生的)。以下是一些:
Zend_Cache - 您可以独立使用它。但它的设计和测试也非常好......
Cache_Lite - 如果您只想要文件缓存。它重量轻,但也不是非常灵活(但这可能是您想要的)。
Kohana 的缓存。它相当灵活,但我不太确定与框架的其余部分分离会有多容易(没有经验)。
关于您的代码的一些评论:
我会使用不同的变量名。 函数中的名称对于它$file_exists的cache()作用来说非常糟糕。它应该是类似的东西$cache_results。使用语义来识别您的姓名。
我真的会把它包装在一个类中,这样你就可以更好地进行初始化。有些事情每个请求你只想做一次,所以没有必要每次都做(稍后会详细介绍)。
清除您的统计缓存!每个请求运行clearstatcache() 一次。其原因是,PHP可以缓存无效的统计信息,并返回错误信息file_exists,filemtime等等。但是它是相当昂贵的,所以我不会运行它超过每一次的请求......
根本不需要使用opendirinread()或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);
}
Run Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
1254 次 |
| 最近记录: |