2011-03-01 65 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