a:
為什麼要使用緩存技術?理由很簡單:提高效率。在程式開發中,擷取資訊的方式主要是查詢資料庫,除此以外,也可能是通過Web Services或者别的某種方法,無論哪種方法,在大量的并發通路面前,它們都可能成為效率的瓶頸,為了解決這些問題,人們提出了很多解決方案,其中一 些是利用優化軟體(如:APC,Eaccelerator,Zend Optimizer等等)來提高程式的運作效率,合理的運用這些軟體,往往能使程式的運作效率得到數量級上的提升,但前提是你必須擁主機的控制權,以便能 夠安裝這些軟體,如果你使用的是虛拟主機的話,那麼隻能祈禱你的服務提供商已經預裝了某個優化軟體,否則就必須自己使用PHP來實作相應的緩存功能。如果 這讓你感到無所适從,相信下面的文字能給你一些啟發。
很多PHP程式員都使用Adodb+Smarty這樣的黃金搭檔,那麼就先看看如何使用它們的緩存功能。
首先看看adodb提供的資料緩存功能:
<?php
include('adodb.inc.php'); # load code common to ADOdb
$ADODB_CACHE_DIR = '/usr/ADODB_cache';
$conn = &ADONewConnection('mysql'); # create a connection
$conn->PConnect('localhost','userid','','agora');# connect to MySQL, agora db
$sql = 'select CustomerName, CustomerID from customers';
$rs = $conn->CacheExecute(15,$sql);
?>
如上,每次查詢資料的時候,會把相應的結果序列化後儲存到檔案中,以後同樣的查詢語句就可以不用直接查詢資料庫,而是從緩存檔案中獲得。
再來看看Smarty提供的頁面緩存功能:
<?php
require('Smarty.class.php');
$smarty = new Smarty;
$smarty->caching = true;
if(!$smarty->is_cached('index.tpl')) {
// No cache available, do variable assignments here.
$contents = get_database_contents();
$smarty->assign($contents);
}
$smarty->display('index.tpl');
?>
如上,每次通路頁面的時候,都會先檢 測相應的緩存是否存在,如果不存在,就連接配接資料庫,得到資料,完成模闆變量的指派,顯示頁面,同時生成緩存檔案,這樣下次通路的時候緩存檔案就發揮作用 了,而不會再執行if塊的資料查詢語句了。當然,在實際使用中會有很多東西要考慮,比如,有效期的設定,緩存組的設定等等,具體可以檢視Smarty手冊 中有關緩存(caching)的相關章節。
以上兩個PHP流行元件緩存方式的側重點是不同的,對于Adodb的緩存而言,它緩存的是資料,對于Smarty的緩存而言,它緩存的是頁面。其他提供緩存功能的元件還有很多(如:PEAR::Cache_Lite等等),實際程式設計中使用哪個方案要具體情況具體分析,也可能會綜合使用。
使用這些元件内置的緩存方案有一個很 明顯的好處是它們的實作對用戶端而言都很透明。隻要進行必要的設定(如:緩存時間,緩存目錄等等)就可以了,而不用過多考慮實作緩存的細節問題,系統會根 據設定自動管理緩存。但是其缺點也同樣明顯,因為每次請求仍然要用PHP解析一遍,效率和純靜态相比還是大打折扣,在大的PV面前還是不能滿足要求,在這 種情況下,僅僅做動态緩存就不夠了,必須實作靜态緩存。
b:
<?php
function cache_isvalid($cacheid,$expire=300) {
@clearstatcache();
if ([email protected]_exists($cacheid)) return false;
if (!([email protected]($cacheid))) return false;
$nowtime=mktime();
if (($mtime+$expire)<$nowtime) {
return false;
}else{
return true;
}
}
function cache_write($cacheid,$cachecontent) {
$retry=100;
for ($i=0;$i<$retry;$i++) {
[email protected]($cacheid,"wb");
if ($ft!=false) break;
if ($i==($retry-1)) return false;
}
@flock($ft,LOCK_UN);
@flock($ft,LOCK_EX|LOCK_NB);
for ($i=0;$i<$retry;$i++) {
[email protected]($ft,$cachecontent);
if ($tmp!=false) break;
if ($i==($retry-1)) return false;
}
@flock($ft,LOCK_UN);
@fclose($ft);
@chmod($cacheid,0777);
return true;
}
function cache_fetch($cacheid) {
$retry=100;
for ($i=0;$i<$retry;$i++) {
[email protected]($cacheid,"rb");
if ($ft!=false) break;
if ($i==($retry-1)) return false;
}
$cachecontent='';
while ([email protected]($ft)) {
[email protected]($ft,4096);
}
@fclose($ft);
return $cachecontent;
}
function cache_clear_expired($cachedirname,$expire=300) {
[email protected]($cachedirname);
while (false!==([email protected]($cachedir))) {
if ($userfile!="." and $userfile!=".." and substr($userfile,-4,4)=='.htm') {
$cacheid=$cachedirname.'/'.$userfile;
if (!cache_isvalid($cacheid,$expire)) @unlink($cacheid);
}
}
@closedir($cachedir);
}
?>