[dev] Кеширование данных

Эта статья рассчитана не просто на сайтостроителей, а на разработчиков, и рассказывает о том, как в Alto CMS устроена система кеширования данных, которая может весьма гибко настраиваться и использовать для хранения данных различные хранилища. В стандартной поставке поддерживаются следующие механизмы кеширования:
  • файловое кеширование (кеш сохраняется на диске)
  • кеширование с использованием Memcached
  • кеширование в XCache
  • и специальный тип кеша (обозначается 'tmp') — данные сохраняются в памяти на время отработки скрипта

Для работы с каждым механизмом есть свой класс PHP. И если Вы захотите написать свой обработчик кеша и использовать какой-то другой механизм (например, Redis), то сделать это можно без особого труда. Досточно создать класс, который будет реализовывать интерфейс ICacheBackend, обеспечивающий доступ к нужной библиотеке.

Настройки кеширования задаются в конфигурационном файле приложения. И те механизмы кеширования, которые разрешено использовать на данном сайте, задаются в конфиг-параметре 'sys.cache.backends'). Если Вы написали свой обработчик, то также должны его добавить в массив 'sys.cache.backends'.

Пара слов про тип кеширования 'tmp' — фактически, в этом случае используются обычные PHP-массивы и этот супербыстрый механизм удобно использовать для краткосрочного хранения данных, которые многократно используются во время исполнения срипта (т.е. обработки URL и отрисовки страницы). Как правило, этот тип кеширования используется при принудительном кешировании (см. ниже).

Режимы кеширования
Предусмотрены следующие режимы кеширования:

Автокеширование — режим, установленный по умолчанию, когда кеширование вообще включено (конфиг-параметр 'sys.cache.use' равен true). Он подразумевает, что задан определенный тип (механизм) кеширования в конфиг-параметре 'sys.cache.type'. В этом случае вызовы Cache->Set(...) и Cache->Get(...) по умолчанию будут сохранять/доставать из кеша данные с помощью механизма, который задан в 'sys.cache.type'. Фактически, это значит, что подавляющее большинство запросов будет в модулях будет использовать это кеширование.

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

Чтобы этот режим был возможен, параметр 'sys.cache.use' должен быть выключен, а тип кеширования в 'sys.cache.type' задан. Если 'sys.cache.type' не задан или заданного в нем механизма кеширования нет в списке 'sys.cache.backends', то кеширование по запросу работать не будет.

Принудительное кеширование — при вызове Cache->Set(...) и Cache->Get(...) может явно задаваться тип кеша (механизм кеширования), который обязательно надо использовать при вызове. Допустимые типы принудительного кеша задаются в конфиг-параметре 'sys.cache.force'. Если они не заданы или указывается тип кеша, которого нет в списке 'sys.cache.backends', то эта опция работать не будет. Обычно этот режим используется с механизмом 'tmp'.

Конкурентные запросы к кешу
При большом трафике возможна ситуация, когда одновременно идет много запросов к одному кешу, который уже «протух». В обычном случае все эти однотипные запросы будут перенаправлены к базе, что значительно увеличивает нагузку на нее. Чтоб этого избежать, сохраняемые в кеше данные дополнительно маркируются временной меткой и заносятся в кеш на несколько бОльший период, чем требуется. И при нескольких одновременных запросах к «протухшему» кешу самый первый запрос вернет значение false и отправится в базу, а остальные запросы в течение определенного времени будут получать старые данные, пока первый запрос не обновит их. Эта опция задается конфиг-параметром 'sys.cache.concurrent_delay'.

Примеры использования
Вот типичный пример использования кеша
if (false === ($data = $this->Cache_Get($sCacheKey))) {
    $data = $this->oMapper->getContentTypeById($nId);
    $this->Cache_Set($data, $sCacheKey, array('content_update', 'content_new'), 60 * 60 * 24 * 1);
}
return $data;
Сначала идет запрос кеша по ключу $sCacheKey (вызов $this->Cache_Get()). Если данных с таким ключом нет (возвращается false), то данные получаются из базы и заносятся в кеш. Обратите внимание, что время хранения кеша можно задавать в двух форматах:
* число секунд (60 * 60 * 24 * 1 — это сутки)
* строкое значение периода в стандарте ISO. Вот так:
$this->Cache_Set($data, $sCacheKey, array(...), 'P1D'); // срок - сутки (1 день)
Чтобы в данном конкретном месте было выполнено кеширование по запросу, вызов должен быть таким:
$this->Cache_Set($data, $sCacheKey, array(...), 'PT12H', true); // срок - 12 часов
Если нужно включить принудительное кеширование, то последним параметром должен быть явно задан тип кеширования (обратите внимание, что параметр «время жизни кеша» в этом случае может быть любым, т.к. он все равно будет игноироваться):
$this->Cache_Set($data, $sCacheKey, array(...), 'P1D', 'tmp');


PS Планируются и другие статьи такого же типа, где будут использоваться технические термины и расписываться подробности, понятные далеко не всем. Возможно, для таких статей нужен отдельный блог, на который могли бы подписаться разработчики? Отпишитесь, пожалуйста

Похожие статьи


9 комментариев

0
Как на счет кеширования ВСЕЙ страницы? и использования механизма кеширования nginx к примеру?
0
Тут речь о кешировании данных. Стандартных средств кеширования контента (за исключением того, что сам Smarty позволяет) в движке нет
Отредактирован:
0
Вы бы лучше продвинутую документацию сделали как на ЛС docs.livestreetcms.com/

Тогда бы многим разработчикам проще было переносить проекты, переделывать плагины или писать с нуля…

Хотя в блоге тоже что-то есть, но только если какие-то плюшки особые описывать, на которых внимание стоит акцентировать…

Зы: В документацию можно не все писать (все таки большая работа), а хотя бы изменения относительно родительского двигла ;)
Отредактирован:
+1
Вы бы лучше продвинутую документацию сделали...
Не очень понятно, о чем речь. По той ссылке все до кучи — и просто блог для разработчиков, и так наз. «API» (а фактически — просто список классов и методов без каких-либо пояснений, как этим добром пользоваться). Сгенерировать список методов, конечно, можно (и сделаем это немного попозже), но вот я, например, за несколько лет работы с ЛС туда ни разу не сходил. А вот статьи — помогали и неоднократно.
0
По той ссылке все до кучи — и просто блог для разработчиков, и так наз. «API» (а фактически — просто список классов и методов без каких-либо пояснений, как этим добром пользоваться)
Вам никто не мешает сделать так, чтоб документация была действительно функциональной, просто еще один блог мало чем поможет. Всегда помогает ПОИСК по блогу ;), если есть в каком материале искать.
Соответственно можно взять типовые задачи и описать для наглядности, так будет реально полезнее, а в каком блоге этот материал размещать — совершенно не важно ;), главное — его полезная нагрузка.

Я почему за документацию вопрос поднял — имею плагин написанный под собственные нужды для ЛС, но при попытке установить его на альту — получаю ожидаемый шиш, даже после пляски с правкой некоторых шаблонов получил на выходе работающий плагин под альтой, но с рост запросов к БД возрос в 4 раза…

Может я и сам бы переделал плагин, чтоб он был совместим с альтой без плагина-посредника (тот самый для обеспечения совместимости), но без понятной документации тех же самых классов у меня ничего не получится, ну или доступного цикла статей по техническим отличиям Альто от ЛС и как осуществить портирование…

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

Но в любом случае — спасибо за отклик.

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

Ладно, все равно спасибо — сама Альта намного привлекательнее чем ЛС в базовой комплектации, но так и не решился поднять проект на ней из-за отсутствия дополнительных плагинов, которые в свою очередь отсутствуют из-за внятной инфы о том как их портировать или писать с нуля… Замкнутый круг короче…
+1
Согласен с leginnn — документация должна быть функциональной и если делать отдельный блог, то лучше сразу определить формат размещаемых топиков:

1. Например в виде подробного мануала по части функционала.
На примере кэширования, я думаю, разработчикам, осваивающим Alto будут интересны, как минимум, следующие вопросы:
      — Типовые способы установки и чтения кэша (ведь практически везде используется код if (false === ($data = ..., но что бы до этого дойти нужно перелопатить кучу кода);
      — Что вообще нужно кэшировать, а что нет;
      — Как формировать имя ключа кэша;
      — Как формировать имя тега и как их, теги, использовать (ведь тегирование в кэше используется для удаления групп данных из кэша, как средство поддержания его актуальности и должны отражать условие очистки (imho), например, как в Alto и сделано в тегах: «topic_update» — очищаем при апдейте топика, «blog_new» — очищаем при добавлении блога...)
      — Какое время жизни тега устанавливать — день, два, неделю (зависит же от способа использования кэша и в одних случаях можно просто установить достаточно большое время потому что кэш обновляется принудительно, а без обновления он будет вечно актуальным. В других же случаях время жизни кэша строго определено)
      — Что за кэш «tmp» (Очень соблазнительно его использовать как суперглобальную область — у меня получилось передать в этот тип кэша данные из модуля, а потом вывести их напрямую из шаблона SMARTY, но должно быть понятно, что это средство оптимизации и используется только с этой целью)
      — Семантика функций (для полноты картины)
      — Дополнительные материалы (например dklab.ru/chicken/nablas/48.html)

Я к чему это все. Перечень вопросов, указанных выше можно освятить и в блоге «Alto CMS inside — как это устроено и работает», если и делать новый блог, то нужно определить:
      — требования к уровню топика — читать же будут люди достаточно понимающие,
      — требования к подаче материала — топик достаточно полно должен описывать проблему — при таком подходе что бы описать функционал Alto потребуется конечное количество топиков, что будет показателем покрытия функционала техническим описанием.

2. Можно определить структуру топиков как cookbook — описание типовых подходов к решению задач — очень и очень полезная штука.

Ну, это, собственно, первое и второе, что в голову пришло )
0
Годная статья. После выхода беты 1.0 — сам разбирался с механизмами кеширования, теперь все намного понятнее.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.