Внимание! Прочитайте, пожалуйста, текст в правой колонке (внизу).
Внимание! Прочитайте, пожалуйста, текст в правой колонке (внизу). Внимание! Прочитайте, пожалуйста, текст в правой колонке (внизу). Homepage Карта сайта Версия для печати

Джентльменский набор Web-разработчика   Ларри Уолл о Perl6   Наблы Система Orphus
 

47. Кэширование: тэги в memcached и не только

[19 апреля 2008 г.] обсудить статью в форуме

Сегодня мы поговорим о работе с кэшем и технологии тэгирования кэша на примере системы memcached. Технические подробности и библиотеку, поддерживающую тэги в memcached, вы найдете в соответствующей статье Конструктора: Dklab_Cache: правильное кэширование — тэги в memcached, namespaces, статистика.

Что такое тэги?

Работа с типичной кэширующей системой (в том числе с memcached) заключается в выполнении трех основных операций:

  • save($data, $id, $lifetime): сохранить данные $data в ячейке кэша с ключом $id. Можно указать "время жизни" ключа $lifetime; спустя это время данные в кэше "протухнут" и удалятся.
  • load($id): загрузить данные из ячейки с ключом $id. Если данные недоступны, возвращается false.
  • remove($id): очистить ячейку кэша с ключом $id.

Предположим, мы хотим эакэшировать долгий SQL-запрос для быстрого отображения части страницы. В этом случае мы проверяем: имеется ли запись в ячейке кэша, соответствующей этому запросу. Если ячейка пуста, данные загружаются из СУБД и сохраняются в кэш для возможных будущих извлечений.

Листинг 1: Типичная работа с кэшем
if (false === ($data = $cache->load("key"))) {
    $data = executeHeavyQuery();
    $cache->save($data, "key");
}
display($data);

К сожалению, в чистом виде этот подход удается применять не так часто. Дело в том, что данные в БД могут измениться, и мы должны каким-то образом очистить ячейку кэша, чтобы пользователь увидел результаты этих изменений немедленно. Можно использовать метод remove() с указанием ключа, однако во многих случаях в момент обновления данных мы просто не знаем, в каких именно ячейках они кэшируются.

Проблема, на самом деле, гораздо сложнее. В высоконагруженных системах данные добавляются в таблицы по нескольку (сотен) раз в секунду. Поэтому логика отслеживания зависимостей и проверки, какие ячейки кэша нужно очищать, а какие — нет, становится крайне сложной (а то и вовсе нереализуемой).

Тэгирование предоставляет решение этой проблемы. Каждый раз, когда данные записываютя в некоторую ячейку кэша, мы помечаем их тэгами — пометками, представляющими зависимости этих данных от других частей системы. Тэги как бы позволяют объединять ячейки в множественные пересекающиеся группы. В дальнейшем мы можем дать команду "очистить все ячейки, помеченные определенным тэгом".

Давайте модифицируем предыдущий пример с использованием тэгов. Предположим, что SQL-запрос существенно зависит от ID текущего пользователя $loggerUserId, поэтому каждому такому пользователю выделяется отдельная ячейка с именем "key_{$loggedUserId}". Однако данные зависят и от ID другого человека $ownerUserId, чей профиль просматривает текущий пользователь. В этом случае мы можем пометить ячейку тэгом, связанным с пользователем $ownerUserId:

Листинг 2: Тэгирование кэша
if (false === ($data = $cache->load("key_{$loggedUserId}"))) {
    $data = loadProfileFor($loggedUserId, $ownerUserId);
    $cache->save($data, "key_{$loggedUserId}", array("profile_{$ownerUserId}");
}
display($data);

Теперь, если меняются данные в профиле пользователя $ownerUserId (например, человек поменял свое имя), нам достаточно дать команду на очистку тэга, связанного с этим профилем:

Листинг 3: Очистка тэга
$cache->clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG, array("profile_{$ownerUserId}");

Обратите внимание, что кэш-ячейки всех остальных пользователей при этом не пострадают: очистятся только те, которые зависели от $ownerUserId.

Собственно, фраза "пометить ячейку C тэгом T" означает то же, что утверждение "ячейка C зависит от данных, описанных как T". Тэги — это зависимости, ничего более.

Кэширование в Zend Framework

В PHP работа с memcached поддерживается отдельным модулем memcache. В нем есть все необходимые операции и методы, однако интерфейс модуля слишком низкоуровневый, чтобы применять его в скриптах. Отличное решение представляет Zend Framework: в нем работа с кэшем четко структурирована и разнесена по уровням абстракции. Именно на основе интерфейсов из Zend Framework работает подсистема Dklab_Cache_Backend, описанная в статье Dklab_Cache: правильное кэширование — тэги в memcached, namespaces, статистика.

В Zend Framework подсистема кэширования разнесена на два логических блока:

  • Zend_Cache_Backend_*: классы, поддерживающие разнобразные хранилища на низком уровне. Каждому хранилищу соответствует свой класс. Имеются, например, классы для кэширования во временных файлах, в SqLite и т. д. Есть и поддержка memcached. Все классы имеют один и тот же интерфейс Zend_Cache_Backend_Interface, включающий методы save(), load(), remove() и т. д.
  • Zend_Cache_Frontend_*: классы-обертки, использующие backend-классы и предоставляющие дополнительную логику по работе с кэшем. Они, например, умеют сохранять структурированные данные (массивы, объекты и т. д.), проводя прозрачную сериализацию и десериализацию.

Backend-классы обычно не используют напрямую, вместо этого применяют frontend-классы. Для каждого frontend-класса можно использовать совершенно любой backend-класс: это достигается благодаря единому интерфейсу backend-кэширования.

Самое приятное и удивительное в Zend_Cache то, что его интерфейсы изначально включают поддержку тэгов! Например, метод save() имеет следующий прототип: save($data, $id, array $tags, $lifetime); как видите, при сохранении данных можно задавать привязанные к ним тэги. Однако эта поддержка для всех backend-ов не реализована: попытка добавить хотя бы один тэг приводит к генерации исключения.

От теории к практике: Dklab_Cache_Backend

Теперь вы знаете, что такое тэгирование и как оно помогает при разработке сложных проектов. Если вам понравилось, переходите к верхней части стати Конструктора Dklab_Cache: правильное кэширование — тэги в memcached, namespaces, статистика и попробуйте предлагаемые решения на практике. В помощью библиотеки Dklab_Cache вы сможете использовать технологию тэгирования ключей на своем сайте.

Ну а затем — возвращайтесь назад и, если все еще осталось желание, читайте следующую наблу Правильный способ кэширования данных, где речь пойдет уже о высокоуровневых аспектах кэширования.

обсудить статью в форуме

 
Рекламный блок
    {{GoogleVertical300: empty}}

На странице:
    47. Кэширование: тэги в memcached и не только
Что такое тэги?
Кэширование в Zend Framework
От теории к практике: Dklab_Cache_Backend

Важное объявление:
    автор категорически против копирования и распространения в Интернете всех статей «Куроводства» с возрастом, меньшим 6 месяцев. Печальный опыт «расползания» чрезвычайно устаревших ошибочных версий статьи про Apache действительно объясняет такое решение.

Орфография на «Куроводстве»:
    если вы заметили орфографическую, стилистическую или другую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter. Выделенный текст будет немедленно отослан вебмастеру, а Вы даже ничего и не заметите — настолько быстро все произойдет.

На заметку:
    если вы уже вскипели насчет дизайна этой страницы, то присмотритесь повнимательнее к названию, почитайте FAQ, сходите по лебедевским местам, как это уже предлагалось выше. Можно ли считать пародию плагиатом? Надеюсь, что нет.

Параметры этой страницы
   
GZip

Ссылки от спонсоров
    {{PromotionBlockRight: empty}}


Дмитрий Котеров | 19 апреля 2008 г. ©1999-2016 | Генеральный спонсор: Хостинг «Джино» | Контакт Вернуться к оглавлению