кэширование запросов
Есть сайт, который состоит из элементов контент которых дергается из бд.
Для снижения нагрузки на сервер БД, можно результат запросов писать в кэш, при этом здесь мы рассмотрим реализацию файлового кэша.
логика работы такова.
прежде чем обратиться к базе с очередным селектом, смотрим, есть ли в специально отведенной папке под это дело файла, отвечающего за конкретно этот запрос. Если файл есть, то прочитать его, если нет, то послать запрос, и результат записать в кэш, чтобы не изобретать велосипед, данные в кеш пишутся сериализоваными.
в идеале это сводится к следующему:
$query='SELECT * FROM `table` ORDER BY id DESC LIMIT 1'; $rez=$cache->get('GET_LAST_POST',$query);
но, это требует от класса еще научится работать с БД, что непременно его усложнит.
поэтому вот модель попроще:
$query='SELECT * FROM `table` ORDER BY id DESC LIMIT 1'; $rez=$cache->is('GET_LAST_POST') ? $cache->get('GET_LAST_POST') : mysql_query($query); $cache->put($rez);
Уже не так красиво, как в первом варианте, зато не требует от будущего класса функций сверх необходимых.
Теперь остановимся подробнее, на структуре класса занимающегося кэшированием.
Наш класс должен знать куда писать, он дожен уметь создавать перезаписывать и удалять файлы, подготавливать данные к помещению и изъятию из кэша.
вот так он выглядит у меня:
class Cache { private $path=''; # путь до папки с кэшем private $str=''; # имя файла кэша private $isStr=false; #есть ли имя private $isCache=false; #есть ли файл по этому имени # устанавливаем путь public function setPath($path){ $this->path=$path; } # передаем имя public function setStr($str){ $str=trim($str); if (strlen($str)<=2){ return false; }else{ $this->str=$this->prepareStr($str); $this->isStr=true; $this->isCache=($this->isFile($this->str))?true:false; return true; } } # возвращаем сгенерированое имя, имя конкретного файла кэша public function getStr(){ return $this->str; } # возвращаем кэш, если есть что public function getCache(){ if ($this->isCache==true){ return file_get_contents($this->path.'/'.$this->str); }else{ return ''; } } # есть ли кэш public function isCache(){ return $this->isCache; } # записать в кэш public function putToCache($str){ if ($this->isStr){ $file = fopen ($this->path.'/'.$this->str,'w'); if ( !$file ) { $this->isCache=false; return false; } else { fputs ( $file, $str); } fclose ($file); if ($this->isFile($this->str)==true){ $this->isCache=true; return true; }else{ return false; } }else{ return false; } } #очстить папку кэша public function clearCache(){ if (empty($this->path) || !file_exists($this->path.'/')){return false;} $dir = opendir ($this->path.'/'); while ( $file = readdir ($dir)){ if (( $file != ".") && ($file != "..") && strlen($file)==32) { if (is_file($this->path.'/'.$file)){$this->deleteFile($this->path.'/'.$file);} } } closedir ($dir); return true; } #физическое удаление файла private function deleteFile($file){ //print $file; unlink($file); } #есть ли файл кэша private function isFile($file){ return (!empty($file) && file_exists($this->path.'/'.$file))?true:false; } #подготавливаем имя файла из переданных параметров private function prepareStr($str){ return md5(strtolower($str)); } }
вроде бы все возможные косяки были учтены, и код работает.
Живой пример использования класса:
include_once('/class/Cache.php'); $cache=new Cache; $cache->setPath('/www/cache'); #cache_code if(isset($cache) && $cache->setStr('GET_NEWS_'.$_GET['id']) && $cache->isCache()){ $aNews=unserialize($cache->getCache()); } else{ $aNews=mysql_query('SELECT * FROM `news` WHERE `id`='.$_GET['id'].' LIMIT 1;'); if (isset($cache)){$cache->putToCache(serialize($aNews));} } #
Комментарии закрыты.