Дата последнего изменения: 23.01.2024
Цитатник веб-разработчиков. Максим Месилов: В 1С-Битрикс есть производительная система кеширования. Она используется как в стандартных компонентах системы, так может быть применена и при самостоятельной разработке. Основная её задача - снизить время отклика сайта и повысить его устойчивость при нагрузках. |
Закладывая в ТЗ проекта интенсивное использование технологии кеширования, можно максимально ограничить нагрузку на базу данных. Это позволит нашему проекту выдержать в будущем значительные нагрузки.
Для реализации кеширования в системе созданы два класса:
Результаты кеширования сохраняются в виде файлов в каталоге /bitrix/cache/
. Если время кеширования не истекло, то вместо ресурсоемкого кода будет подключен предварительно созданный файл кеша.
Правильное использование кеширования позволяет увеличить общую производительность сайта на порядок. Однако необходимо учитывать, что неразумное использование кеширования может привести к серьезному увеличению размера каталога /bitrix/cache/
.
Пример кеширования HTML
<? // создаем объект $obCache = new CPageCache; // время кеширования - 30 минут $life_time = 30*60; // формируем идентификатор кеша в зависимости от всех параметров // которые могут повлиять на результирующий HTML $cache_id = $ELEMENT_ID.$IBLOCK_TYPE.$USER->GetUserGroupString(); // инициализируем буферизирование вывода if($obCache->StartDataCache($life_time, $cache_id, "/")): // выбираем из базы параметры элемента инфоблока if($arIBlockElement = GetIBlockElement($ELEMENT_ID, $IBLOCK_TYPE)): echo "<pre>"; print_r($arIBlockElement); echo "</pre>"; endif; // записываем предварительно буферизированный вывод в файл кеша $obCache->EndDataCache(); endif; ?>
В данном примере, метод CPageCache::StartDataCache проверит наличие неистекшего и валидного файла кеша. Если такой файл существует, то он будет подключен и выведен на экран, в противном случае будет включена буферизация. Результаты буферизации будут записаны в файл кеша методом CPageCache::EndDataCache.
В первом параметре метода CPageCache::StartDataCache задается интервал времени в секундах, в течение которого файл кеша будет считаться валидным и не истекшим (интервал времени отсчитывается с момента создания файла кеша).
Во втором параметре указывается уникальный идентификатор данного экземпляра кеша. Здесь необходимо подчеркнуть, что если какие-либо переменные могут повлиять на результат выполнения кешируемого кода, то их значения необходимо включить в этот идентификатор.
Например:
Пример кеширования HTML и PHP переменных
<? // создаем объект $obCache = new CPHPCache; // время кеширования - 30 минут $life_time = 30*60; // формируем идентификатор кеша в зависимости от всех параметров // которые могут повлиять на результирующий HTML $cache_id = $ELEMENT_ID.$SECTION_ID.$USER->GetUserGroupString(); // если кеш есть и он ещё не истек то if($obCache->InitCache($life_time, $cache_id, "/")): // получаем закешированные переменные $vars = $obCache->GetVars(); $SECTION_TITLE = $vars["SECTION_TITLE"]; else : // иначе обращаемся к базе $arSection = GetIBlockSection($SECTION_ID); $SECTION_TITLE = $arSection["NAME"]; endif; // добавляем пункт меню в навигационную цепочку $APPLICATION->AddChainItem($SECTION_TITLE, $SECTION_URL."SECTION_ID=".$SECTION_ID); // начинаем буферизирование вывода if($obCache->StartDataCache()): // выбираем из базы параметры элемента инфоблока if($arIBlockElement = GetIBlockElement($ELEMENT_ID, $IBLOCK_TYPE)): echo "<pre>"; print_r($arIBlockElement); echo "</pre>"; endif; // записываем предварительно буферизированный вывод в файл кеша // вместе с дополнительной переменной $obCache->EndDataCache(array( "SECTION_TITLE" => $SECTION_TITLE )); endif; ?>
Отличие данного примера от предыдущего заключается в том, что помимо HTML также кешируется PHP переменная $SECTION_TITLE
. Структура и тип кешируемых PHP переменных могут быть произвольными. Метод CPHPCache::InitCache выполняет проверку на наличие неистекшего и валидного файла кеша. Если данный файл найден, то происходит его подключение, при этом все закешированные переменные будут доступны после использования метода CPHPCache::GetVars. Метод CPHPCache::EndDataCache, помимо буферизированного HTML кода, записывает в файл кеша также PHP переменные.
Для отключения кеширования на одной странице, необходимо авторизоваться с административными правами и вызвать эту страницу с параметром &clear_cache=Y
. Если, авторизовавшись с административными правами, вызвать любую страницу с параметром &clear_cache_session=Y
, то кеш будет отключен для всех страниц, которые будут просмотрены в рамках сессии. Файлы кеша можно удалить в административной части на закладке Очистка файлов кеша страницы Настройки > Настройки продукта > Автокеширование.
Смотрите также:
Мы убедились, что использовать технологию кеширования для веб-сайта нужно, значит необходимо предусмотреть кеширование ещё на стадии написания ТЗ.
Допустим, через определенное время, наш веб-сайт стал популярным ресурсом. Благодаря активному использованию технологии кеширования мы надежно защитили базу данных от высокой нагрузки, и она может выдержать 3-5 кратное превышение нагрузки.
Однако, у нас, из-за специфики веб-сайта, скопился большой объем самих закешированных данных, использование которых (десятки тысяч файлов) вызывает "некоторые" неудобства - возросла нагрузка на дисковую подсистему. А также, к сожалению, при разработке вкрались ошибки и наши закешированные данные чистятся не полностью, поэтому постепенно их объем на диске становится все больше и больше...
Решения есть:
memcached
При использовании memcached временные данные будут храниться в оперативной памяти. Можно выделить для хранения кеша недорогой сервер с несколькими гигабайтами памяти.
При этом, устаревшие данные будут автоматически вытесняться и наш кеш перестанет "расползаться" по системе, пожирая все больше и больше места. Допустим, мы выделили в memcached 4GB места для кеширования и можем быть уверенными, что больше 4GB кеш не вырастет, а наименее часто используемые данные будут вытесняться (алгоритм LRU). Очень удобно и эффективно.
Подключение memcached осуществляется в файле dbconn.php.
Для эффективной работы системы настройки по умолчанию нужно изменить. Примеры:
// Мемкеш с объемом памяти 2ГБ 8 потоками и работой через tcp PORT="11211" USER="memcached" MAXCONN="10240" CACHESIZE="2048" OPTIONS="-t 8" // настройки в dbconn.php define("BX_CACHE_TYPE", "memcache"); define("BX_CACHE_SID", $_SERVER["DOCUMENT_ROOT"]."#01"); define("BX_MEMCACHE_HOST", "127.0.0.1"); define("BX_MEMCACHE_PORT", "11211");
// Мемкеш с объемом памяти 2ГБ 8 потоками и работой через сокет PORT="11211" USER="bitrix" MAXCONN="10240" CACHESIZE="2048" OPTIONS="-t 8 -s /tmp/memcached.sock" // настройки в dbconn.php define("BX_CACHE_TYPE", "memcache"); define("BX_CACHE_SID", $_SERVER["DOCUMENT_ROOT"]."#01"); define("BX_MEMCACHE_HOST", "unix:///tmp/memcached.sock"); define("BX_MEMCACHE_PORT", "0");
Если memcached используется на одной машине, там же, где и находится сам веб-сервер, то использование сокета будет быстрее.
Ссылки по теме:
APC
Подключение APC осуществляется в файле dbconn.php:
// настройки в dbconn.php define("BX_CACHE_TYPE", "apc"); define("BX_CACHE_SID", $_SERVER["DOCUMENT_ROOT"]."#01");
Подробнее про установку и настройку APC смотрите в документации www.php.net/apc.
Очень часто встречающаяся проблема при работе с кешем - в закладке Хранение кеша страницы Настройки > Производительность > Панель производительности появляется параметр cacheenginenone, а кеширование при этом не производится. По сути данный параметр - это указание системы, что выбранный вами способ хранения кеша не работает. Можно сказать, что подходящего способа кеширования для системы нет, поэтому она и не будет выполнять его, как будто оно не включено вовсе.
Для того, чтобы решить эту проблему, нужно правильно настроить способ кеширования. Например, данный параметр может появиться, если вы указываете, что кеш должен храниться c помощью APC, но данное приложение настроено неправильно или отключено. Вам нужно проверить его настройки или включить его, если требуется.
Смотрите также:
Подробное описание кеширования в компонентах описано в уроке Кеширование в собственных компонентах в рамках главы Компоненты.
Юналиев Рамиль: Если разработчик делает 1000 запросов и говорит "и так сойдет, оно же кешируется", то это конечно неправильно, любым инструментом нужно уметь пользоваться.
Сербул Александр: Иногда во время разработки активно используются технологии кеширования, однако при возрастании нагрузки база данных подвергается перегрузкам. Почему? Для предупреждения данного риска необходимо сначала обеспечить наиболее оптимальную работу с базой данных с выключенным кешированием, прежде чем его включать (рекомендую менеджерам интернет-проектов взять это на заметку и включить в чеклист контроля качества проекта). Типичный кейс данной "ловушки" такой - при включенном кешировании кастомизированное меню использует 0 SQL-запросов, при выключенном - 5000!
Лучше установить большее время кеширования, а актуальность данных в кеше поддерживать с помощью Тегированного кеширования. Тогда кеш будет обновляться только при изменении данных, а соответственно не будет лишней нагрузки на сервер, как в случае с малым временем, когда кеш создается по истечении указанного периода времени независимо от актуальности данных.
Пример создания кеша для новостей, когда срок активности новости скоро истекает, и кеш достаточно будет создать на весь день всего один раз:
// Не правильный ИД, так как в данном случае на каждый хит будет создан новый кеш. // (При условии что нам надо выбрать все элементы которые на данный день активны.) $arFilter = array( 'IBLOCK_ID' => 19, 'ACTIVE' => 'Y', '>=PROPERTY_end_date' => date("Y-m-d H:i:s") ); $CACHE_TIME = 86400; $CACHE_ID = "some_key_iblock".implode('_', $arFilter); $obCache = new CPHPCache; if($obCache->InitCache($CACHE_TIME, $CACHE_ID, "/")) { $arVars = $obCache->GetVars(); }
// Правильный ИД, так как в данном случае кеш будет создан на весь день. // (При условии что нам надо выбрать все элементы которые на данный день активны.) $arFilter = array( 'IBLOCK_ID' => 19, 'ACTIVE' => 'Y', '>=PROPERTY_end_date' => date("Y-m-d 00:00:00") ); $CACHE_TIME = 86400; $CACHE_ID = "some_key_iblock".implode('_', $arFilter); $obCache = new CPHPCache; if($obCache->InitCache($CACHE_TIME, $CACHE_ID, "/")) { $arVars = $obCache->GetVars(); }
Ссылки по теме: