Уже много описано про memcache, однако я помучался прежде чем нашел оптимальный вариант для одного проекта на PHP, достаточно ресурсоемкого с большим объемом расчетов в Kohana.
Memcache пришлось отфутболить сразу же, так как когда ключей набегает пару сотен, нереально отследить, когда и какой ключ нужно убить. Смотрел в сторону MemcacheTag, где применено использование тэгов для объединения нескольких ключей, однако он оказался слишком сырым и весьма неудобным для работы. В конце концов был найден самый, на мой взгляд, оптимальный вариант работы с memcached.
Описание принципа работы данной технологии лучше всего посмотреть здесь
или на первоисточнике.
Я же напишу как подключать и использовать в фреймворке Kohana, каким образом отследить ключи кэшей и собственно протестировать как работает кэширование в проекте.
Итак, начнем:
В bootstrap раскомментировать 'cache'=> MODPATH.'cache', добавить файл MODPATH/cache/classes/Cache/Memcacheimp.php
вот такого вида:
class Cache_Memcacheimp extends Kohana_Cache_Memcacheimp {}
Добавить файл в MODPATH/cache/classes/Kohana/Cache/Memcacheimp.php.
Ниже файл для скачивания.
Скопировать MODPATH/cache/config/cache.php, вставить его в application config и добавить туда, как последний элемент массива, следующий код:
'memcacheimp' => array(
'driver' => 'memcacheimp',
'default_expire' => 3600,
'compression' => FALSE,
'servers' => array(
'local' => array(
'host' => 'localhost',
'port' => 11211,
'persistent' => FALSE,
'weight' => 1,
'timeout' => 1,
'retry_interval' => 15,
'status' => TRUE,
),
),
'instant_death' => TRUE,
'statistics' => FALSE,
)
где установлены стандартные элементы по умолчанию для кэширования, кроме ключа 'statistics', который я добавил для тестирования. Он включает и выключает тестирование нашего memcached.
Все теперь можно работать.
Вызов метода:
Model_SomeClass::factory('table')->get($id, 'key_tag');
где key_tag — объеденяющий тег для нескольких ключей
Создаем объект:
$this->cache = Cache::instance('memcacheimp');
Таким образом, создаем cache в модели:
public function get($id, $tags = null)
{
$cOne = $this->cache->get("get_{$this->_table}_{$id}");
if (!is_array($cOne))
{
$query = DB::query(Database::SELECT, "SELECT * FROM $this->_table WHERE id='$id'");
$cOne = $query->execute()->as_array();
$this->cache->set("get_{$this->_table}_{$id}", $cOne, array($tags));
}
return $cOne;
}
Так убиваем cache c ключами объедененными тегом key_tag:
$this->cache->delete_tag('key_tag');
Чтобы убить весь cache или удалить по ключу, пользуемся стандартными методами cache, так как наш класс наследуется от Cache.
Для того, чтобы проследить процесс работы нашего кеширования и понять, какие ключи у нас создаются, изменим немножко конфиг:
'statistics' => TRUE,
Теперь мы можем посмотреть, что происходит с нашим кэшем. Открываем APPPATH/cache/statistics/ и смотрим содержимое файла get_someTable_someId.txt, где get_someTable_someId — имя нашего ключа.
MLWHHHHH
М — кэш отсутствует
L — установлена блокировка ключа
Н — успешный запрос кеша
То есть, наш кеш прекрасно работает.
Ну и результат до и после кеширования:
Как видно, довольно таки тяжелая страница с множеством обращений к базе грузится за 0,455 сек. против 1,7 сек. до кеширования
Скачать Memcacheimp.php можно здесь.
Автор: navikom