Главная > Open Source, PHP, Высокопроизводительная архитектура > Работаем с кешами через ezComponents — файловый, APC, memcached.

Работаем с кешами через ezComponents — файловый, APC, memcached.

3 декабря 2007

ezcomponents.jpgПриветствую наших читателей. Не так давно мы подняли тему enterprise-ready фреймворков и компонент для РНР, которые можно использовать в больших и серьёзных проектах. А когда подняли, то исследовали немного довольно старый, но активно развивающийся проект ezComponents, кстати, на днях вышла первая бета последней версии - 2007.2.

Некоторое время я все присматривался к этим компонентам, теперь же буду планомерно внедрять его поддержку в свой текущий масштабный проект (кто не знает, онлайновая стратегическая игра, широко использующая AJAX). А результатами своих работ по части ezComponents буду делится с нашими читателями. Да, сразу предупрежу вопросы, почему я не использую популярный сейчас (да и мощный, да, тут нечего сказать) фреймоворк Zend Framework, который также обновился до версии 1.0.3. Для меня лично он неудобен тем, что навязывает свою парадигму реализации всей архитектуре на основе MVC. И хотя в ezComponents это также возможно, но гораздо удобнее чтобы библиотека просто предоставляла различные компоненты и возможности, что позволит встроить её в любое уже работающие приложение, а не перепроектировать его с нуля, даже если это позволит поднять разработку на новый качественный уровень (что, собственно, ещё тоже под вопросом). Поэтому мы выбрали в качестве базового фреймворка все же ezComponents, правда не весь, а пока всего лишь несколько компонент, в первую очередь модуль кёша, который в этой библиотеке просто отличный.

И так, приступим. В библиотеке реализованы следующие виды кёшей:

  • ezcCacheStorageFile - базовый абстрактный класс файлового кёша, который хранится по заданному пути, например в каталоге /tmp/cache.
    • ezcCacheStorageFileArray
    • ezcCacheStorageFileEvalArray
    • ezcCacheStorageFilePlain
  • ezcCacheStorageMemory - базовый класс для кёширования в памяти, используя различные механизмы - memcached или кёширующий акселератор APC. Жаль, пока нет модуля для поддержки XCache, но его не должно быть сложно написать.
    • ezcCacheStorageMemcachePlain
    • ezcCacheStorageApcPlain
    • ezcCacheStorageFileApcArray
  • ezcCacheManager - базовый класс менеджера кёшей, который предоставляет унифицированный интерфейс для работы одновременно с множеством кёшей, в том числе и различных по типу.

Сразу развею одно из мнений, что ezComponents очень ресурсоёмкая библиотека. Да, там множество компонентов, но если выбрать именно те, которые вам нужны, то вполне обычное приложение получается. Например, если вы будете использовать только модуль кёширования, то вам следует с полного дистрибутива (который имеет размер около 20 мегабайт, но это вместе с тестами и документацией для каждого модуля) взять только три компонента (директории):

  • autoload - содержит файлы для автоматического подключения классов (используется функция __autoload из РНР 5). Из неё можно спокойно удалить все файлы модулей, которые не используются.
  • Base - содержит базовый код инициализации и необходим для работы библиотеки. В этой директории есть несколько подкаталогов, из них можно оставить только src (с остальными модулями точно так же), остальные содержат тесты и документацию, которая пригодится очень при разработке, но в готовом приложении может быть удалена. А если ещё и оптимизировать сами файлы, убрав оттуда все комментарии, которых достаточно много, то есть возможность ещё более кардинально уменьшить объем подключаемых файлов.
  • Cache - здесь как раз сосредоточен весь код модуля кёширования, реализации классов для работы с различными видами и типами кёшей.

А теперь попробуем сделать первые шаги в освоении её возможностей.

Сначала инициализируем библиотеку, подключая её базовый класс.

require_once('ezc/Base/src/base.php');
function __autoload( $className )    {

ezcBase::autoload( $className );

}

Этот код лучше всего вынести в отдельный подключаемый файл и расположить в директории inc, там же, в папке ezc я расположил исходники самой библиотеки. А далее этот файл мы просто подключаем на каждой странице, где требуется получить доступ к компонентам ezComponents.

Первым делом нам нужно создать массив конфигурации кёшей. В данном случае я лично считаю, что есть некоторая недоработка, например, хотя интерфейс работы с менеджером кёшей унифицирован, но массив конфигурационных данных нельзя использовать с другими. Например, если мы создаём конфигурацию для работы с memcached, там указывается host, port и другие данные, то его нельзя использовать с файловым кёшем, хотя ему нужен только один параметр, ttl, остальные можно было просто игнорировать, но при попытке генерируется исключение - ezcBasePropertyNotFoundException.

Но вернёмся к опциям. Их всего пять:

  • ttl - время жизни кёша, то есть, сколько времени он хранит актуальные данные. Целое число в секундах. Эта опция общая для всех типов кёширования, файловый и APC кёши требуют только этой опции.
  • host - указывает на хост, на котором запущен демон memcached. Используется только для этого типа кёша.
  • port - порт, который слушает демон memcached.
  • persistent - указывает на использование постоянного соединения с демоном memcached. По умолчанию установлено в false, но не спешите переставлять его - для высоконагруженных проектов, где кёш будет использоваться активно, это может быстро привести к исчерпанию соединений.
  • compressed - указывает на использование сжатия на лету, используя PHP расширение zlib. По умолчанию также установлено в false. В принципе, может быть полезным при хранении больших объемов текстовых данных, например, шаблонов и контента, которых хорошо сжимается стандартными алгоритмами. Но это вызовет дополнительную нагрузку на CPU и внесёт некоторые задержки на компрессию данных.

Мы для тестирования будем работать с двумя типами кёшей, поэтому создадим два массива конфигураций - для файлового кёша и memcached:

$options_mem = array(

	'ttl'   => 30,

	'host' => 'localhost',

	'port' => 11211,

	'persistent' => false,

	'compressed' => true

);

$options_file = array(

	'ttl'   => 30

);

В обоих случаях у нас время жизни установлено в 30 секунд.

Теперь, как у нас все готово, создаём кёши, используя менеджер. Сначала создаём файловый кёш - для него нужно указать каталог, в котором будут хранится данные, а также идентификатор кёша, по которому в последствии мы сможем получить доступ (он должен быть уникальным!):

ezcCacheManager::createCache( 'test_cache', '/tmp/cache', 'ezcCacheStorageFilePlain', $options_file);

Теперь этот кёш доступен нам для работы, используя его идентификатор "test_cache"? а сами данные будут храниться в файлах, расположенных в каталоге /tmp/cache.

Для работы с memcached необходимо только поменять некоторые переменные - именно при работе с разными модулями и прелесть использования менеджера, хотя, конечно, можно и вручную каждый кёш инициализировать напрямую, если вы используете только один вид кёширования, то так можете ещё немного сократить время инициализации и ресурсоёмкость приложения.

ezcCacheManager::createCache( 'test_memcache', null, 'ezcCacheStorageMemcachePlain', $options_mem);

Теперь мы инициировали и второй кёш. Если не возникло никаких исключений, значит все прошло нормально и можно начинать работу.

Используя менеджер и идентификатор, получим наш кёш:

$cache = ezcCacheManager::getCache( 'test_cache' );

Каждый кёш поддерживает универсальный API доступа, поэтому мы рассмотрим его только один раз.

  • store - функция принимает идентификатор, сами данные (в основном, это строки, объекты можно хранить в сериализированном виде, а в кёшах в память можно передавать объекты напрямую) и, опционально, массив атрибутов для описания данных.
  • restore - возвращает данные с кёша, если они там есть и ещё валидные, в противном случае возвращается false, а сами данные удаляются. Может принимать ещё массив атрибутов и флаг использования поиска, если данные не нашлись по их идентификатору.
  • delete - удаляет данные из кёша по их идентификатору или атрибутам. Если заданы только атрибуты, то удаляются все данные с совпавшими атрибутами. Например, выставляя в качестве атрибута идентификатор языка, вы потом можете не перебирая все идентификаторы, просто указать, что удалить из кёша данные для одного языка и все.
  • countDataItems - позволяет узнать, сколько подходящих под определение (согласно ID или атрибутам) переменных хранится в кёше.
  • getRemainingLifetime - показывает в секундах время до момента истечения срока валидности объекта в кёше.
  • getOptions/setOptions - позволяет получить или установить значение опций.

Теперь схема работы достаточно ясна. Самый простой случай - это сначала запросить нужный нам объект из кёша, предварительно, конечно, получив его от менеджера, и сравнить ответ со значением boolean false, если так, то объекта в кёше нет или он уже просрочен, и тогда записать его, иначе мы получим его сохранённую копию.

Это можно сделать так:

$myTest = 'Просто тестовая строка. Сохранено: ';
$cache = ezcCacheManager::getCache( 'test_cache' );
if ( ( $_myTest = $cache->restore( 'test_var' ) ) === false )
 {
 	$myTest = $myTest  . date( 'Y-m-d, H:i:s' );
 	$cache->store( 'test_var', $myTest );
 }
 else
 {
 	$myTest = $_myTest;
 }

Конечно, в реальном приложении это можно сделать гораздо более элегантно и архитектурно верно, но я всего лишь показываю сам принцип работы с компонентами кёша из ezComponents. Кстати, вы заметили, что нам совсем без разницы, в каком кёше сохранена переменная, всё, что нам нужно - это идентификатор кёша. Кстати, вопрос для изучения: если кёшей может быть одновременно сколько угодно много, и различных типов, то можно ли найти переменную, вообще не зная, в каком конкретно она кёше (без его идентификатора), или для этого писать свою функцию перебора всех зарегистрированных в менеджере кёшей?

Ну вот, пожалуй и всё. Если вам интересна эта тема, дальнейшую подробную информацию вы найдёте в документации, исходном коде и комментариях, а также в примерах, поставляемых с каждым компонентом из библиотеки. Поверьте, качество документации такое, что позволяет совершенно по новому взглянуть на подход к документированию других разработок. Это действительно промышленное решение. Для примера только взгляните на диаграмму классов:

cache.png

UML диаграмма классов - class_diagram.png

  1. 3 декабря 2007 в 18:07 | #1

    Поправьте заголовок.

  2. 3 декабря 2007 в 18:12 | #2

    что и где именно?

  3. 3 декабря 2007 в 19:02 | #3

    «Работаем с кёшами»
    ё-е

Комментирование отключено.