Настройка кеширования кастомных компонентов 1С-Битрикс
Компонент без кеширования — это запрос к базе данных при каждом просмотре страницы. При 1 000 просмотров в сутки это 1 000 запросов; при 10 000 — уже реальная нагрузка. Кеширование в Битрикс — не волшебная кнопка «включить», это набор конкретных решений: что кешировать, как долго, по какому ключу, и как инвалидировать при изменении данных.
Механизм кеширования Битрикс
Битрикс использует файловый кеш по умолчанию. Кеш хранится в /bitrix/cache/ (или в /upload/cache/ в зависимости от конфигурации). Каждый кеш-файл — сериализованный $arResult компонента. При попадании в кеш template.php вызывается с кешированными данными — никаких запросов к БД.
Два уровня кеширования:
-
Кеш результата (
StartResultCache/EndResultCache) — кешируется$arResult - Кеш HTML (composit-кеш, отдельный механизм) — кешируется итоговый HTML
Для кастомных компонентов используется первый уровень.
Базовое использование StartResultCache
// component.php
$cacheId = serialize([
$arParams['IBLOCK_ID'],
$arParams['COUNT'],
$arParams['SECTION_ID'],
LANGUAGE_ID,
SITE_ID,
]);
$cacheDir = '/custom/my.component/' . $arParams['IBLOCK_ID'] . '/';
if ($this->StartResultCache($arParams['CACHE_TIME'], $cacheId, $cacheDir)) {
// Этот блок выполняется только при отсутствии кеша
$this->arResult = $this->getData();
$this->IncludeComponentTemplate();
$this->EndResultCache();
}
Параметры StartResultCache($cacheTime, $cacheId, $cacheDir):
-
$cacheTime— TTL в секундах.falseили0— кеш не используется.-1— кеш бесконечный (до ручной инвалидации) -
$cacheId— уникальный идентификатор данного набора параметров. При разных параметрах компонента должен быть разным — иначе все варианты покажут одни и те же данные -
$cacheDir— папка в/bitrix/cache/. Нужна для группового сброса кеша одного компонента
Правильное формирование cacheId
Ошибка, которую допускают при первой реализации: $cacheId не учитывает все влияющие параметры. В итоге страница с разделом «Электроника» показывает кеш от страницы «Одежда».
Что обязательно должно входить в cacheId:
$cacheId = serialize([
// Параметры компонента, влияющие на результат
$arParams['IBLOCK_ID'],
$arParams['SECTION_ID'],
$arParams['COUNT'],
$arParams['ELEMENT_SORT_FIELD'],
// Контекст
LANGUAGE_ID, // мультиязычность
SITE_ID, // мультисайтовость
// Если контент зависит от группы пользователя
// serialize(CSaleUser::GetUserGroups()), -- только если нужно
]);
Не включать в cacheId то, что не влияет на данные — иначе кеш не будет использоваться. Например, CSS-класс блока ($arParams['CSS_CLASS']) — это параметр отображения, не данных. Его применяют в template.php напрямую из $arParams, а не через $arResult.
Кеш с учётом групп пользователей
Если компонент показывает разный контент авторизованным и гостям (например, цены для B2B-клиентов отличаются от розничных), кеш должен быть раздельным:
// Вариант 1: кеш выключен для авторизованных пользователей
global $USER;
$cacheTime = $USER->IsAuthorized() ? false : $arParams['CACHE_TIME'];
// Вариант 2: включить разделение по группам (тяжелее)
$arParams['CACHE_GROUPS'] = 'Y'; // параметр включает разделение по группам в Битрикс
Параметр CACHE_GROUPS => 'Y' в стандартных компонентах Битрикс автоматически добавляет группы пользователя в cacheId. В кастомном компоненте это нужно сделать вручную:
if ($arParams['CACHE_GROUPS'] === 'Y') {
$userGroups = CSaleUser::GetUserGroups();
sort($userGroups);
$cacheId = serialize([$baseParams, $userGroups]);
}
Инвалидация кеша при обновлении данных
TTL-кеш (кеш по времени) — самое простое решение, но неточное: изменённый в 10:00 элемент инфоблока станет видимым только через 1 час (если CACHE_TIME = 3600). Для контента, где актуальность важна, нужна инвалидация по событию.
Обработчик события инфоблока:
// В /local/php_interface/init.php
AddEventHandler('iblock', 'OnAfterIBlockElementUpdate', 'clearMyComponentCache');
AddEventHandler('iblock', 'OnAfterIBlockElementAdd', 'clearMyComponentCache');
AddEventHandler('iblock', 'OnAfterIBlockElementDelete', 'clearMyComponentCache');
function clearMyComponentCache($arFields) {
// Сбрасываем кеш только для нужного инфоблока
if (!in_array($arFields['IBLOCK_ID'], [IBLOCK_CATALOG_ID, IBLOCK_NEWS_ID])) {
return;
}
// Сброс всей папки кеша компонента
BXClearCache(true, '/custom/my.component/' . $arFields['IBLOCK_ID'] . '/');
}
BXClearCache(true, $path) — удаляет все файлы в указанной папке кеша. Быстро и без ORM.
Тегированный кеш: точечная инвалидация
Если компонент показывает данные из нескольких инфоблоков, общий сброс кеша при изменении любого из них — расточительно. Тегированный кеш решает это точнее:
use Bitrix\Main\Data\TaggedCache;
$taggedCache = new TaggedCache();
$taggedCache->startTagCache('/custom/my.component/');
if ($this->StartResultCache($cacheTime, $cacheId, $cacheDir)) {
$taggedCache->registerTag('iblock_id_' . $arParams['IBLOCK_ID']);
$taggedCache->registerTag('iblock_element_' . $elementId); // при кеше конкретного элемента
$this->arResult = $this->getData();
$this->IncludeComponentTemplate();
$taggedCache->endTagCache();
$this->EndResultCache();
} else {
$taggedCache->abortTagCache();
}
Инвалидация по тегу при изменении конкретного элемента:
// В обработчике события
$taggedCache = new TaggedCache();
$taggedCache->clearByTag('iblock_element_' . $arFields['ID']);
$taggedCache->clearByTag('iblock_id_' . $arFields['IBLOCK_ID']);
Тегированный кеш более точный, но требует больше кода. Оправдан для высоконагруженных проектов с частыми обновлениями данных.
Отладка кеша
Кеш можно отключить для конкретного компонента в режиме разработки:
// В component.php во время отладки
$cacheTime = defined('DEVELOPER_MODE') && DEVELOPER_MODE ? false : $arParams['CACHE_TIME'];
DEVELOPER_MODE определяется в /bitrix/.settings.php или в константах проекта. При false кеш пропускается, данные всегда запрашиваются из БД.
Просмотр кеша: файлы в /bitrix/cache/ доступны напрямую — это PHP-файлы с serialize() данными. Время создания файла — время последнего прогрева кеша.
Кеш и AJAX-запросы
Для компонентов с AJAX-обновлением (подгрузка товаров при пагинации) кеш применяется к каждому запросу отдельно. cacheId для AJAX-запроса включает параметры запроса:
$page = max(1, (int)$_REQUEST['page']);
$cacheId = serialize([$baseParams, $page]);
Каждая страница пагинации кешируется отдельно — это правильно.
Сроки настройки
| Задача | Срок |
|---|---|
| Базовое кеширование для компонента | 2–4 часа |
| + Инвалидация по событиям | 4–8 часов |
| + Тегированный кеш | 1–2 дня |
| Аудит существующих компонентов + исправление | 1–3 дня |
Кеширование — одна из немногих оптимизаций, которая даёт мгновенный и измеримый результат. Правильно настроенный кеш снижает время генерации страницы с 500 мс до 20–50 мс без изменения логики приложения.







