2011-03-01 64 views
2

HI。PHP PEAR Cache_Lite

因为我使用共享托管软件包,并且即时通讯无法使用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作品几乎同样的方式,和我不熟悉梨缓存系统,我想知道什么是更好,更安全和更快的解决方案之间使用这两个,为什么?

谢谢!

+0

的开始,经编所有你在一个类码,然后allso可以保持“文件句柄”打开,直到应用程序完成请求,这不是很好的解决方案,打开和关闭文件很多次。 – 2011-03-01 13:35:51

+0

是否安装了Memcache? – powtac 2011-03-01 13:36:35

+0

这可能属于[CodeReview.StackExchange](http://codereview.stackexchange.com/)... – ircmaxell 2011-03-01 13:42:36

回答

4

就我个人而言,我会为此使用一个库。写一个缓存层看起来要困难得多。这并不难,你不能做到这一点,但很难将所有边缘情况和怪癖排除在系统之外。你可以使用像Cache_Lite这样的东西,但我会建议一个更好的缓存层。其中有几个(独立和框架出生)。这里有几个:

  • Zend_Cache - 你可以使用这个独立的。但它也是很好的设计和测试...

  • Cache_Lite - 如果你只想要文件缓存。它重量轻,但也不是非常灵活(但这可能是你想要的)。

  • Kohana's cache。它非常灵活,但我不确定从框架的其余部分分离(没有经验)是多么容易。

你的代码的一些意见:

  1. 我会用不同的变量名。 $file_existscache()函数中是一个非常糟糕的名字。它应该是像$cache_results。使用语义来识别你的名字。

  2. 我真的把这个包装在一个类中,所以你可以更好地进行初始化。有些事情您只需要针对每个请求执行一次,因此无需每次都做(稍后再介绍一点)。

  3. 清除你的状态缓存!每个请求运行clearstatcache()一次。其原因是,PHP可以缓存无效的统计信息,并返回错误信息file_existsfilemtime等,但它是相当昂贵的,所以我不会运行它超过每一次请求更多...

  4. 有没有必要在read()write()中完全使用opendir。如果您想验证目录是否存在,请致电is_dir($dir)。现在,你正在打开一个句柄,并无所作为。

  5. 您在read()write()中都有资源泄漏,其中存在打开目录但未关闭目录的路径。虽然这在大多数情况下都不是什么大问题,但请妥善关闭资源。(更好的是,完全消除呼叫)。

  6. 请勿使用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); 
    } 
    
+0

thanx很多关于我的代码的评论和提示,我发现它对改进这个功能非常有用。大概,我会用你提到的一些库:) – devilsreject 2011-03-01 14:19:09