Кеширование в 1С-Битрикс - автокеш, D7 Cache, тегированный кеш
В 1С-Битрикс несколько независимых механизмов кеширования, и их принято совмещать: каждый участок кешируется подходящим способом. Разберём все уровни, правила формирования ключей и главную проблему любого кеша - своевременный сброс.
Как это работает
Автокеширование компонентов. Штатные компоненты сохраняют результат в файлы и на повторных запросах не обращаются к базе вовсе. Режимы три: «Авто плюс управляемое» - обновление и по времени, и при изменении данных; «Кешировать» - только по времени жизни; «Не кешировать».
Обычный кеш не перестраивается при изменении данных и живёт заданное время.
Подходит там, где допустима небольшая задержка актуальности. В новом коде для
своих данных используют класс Bitrix\Main\Data\Cache, в старом встречается
CPHPCache.
Управляемый кеш хранится отдельно и сбрасывается точечно по ключу или каталогу. Привязка к таблице ORM даёт автоматический сброс после добавления, изменения или удаления записи.
Тегированный кеш - это механизм инвалидации поверх обычного кеша. Записи помечаются тегом, и одно доменное изменение сбрасывает все записи с этим тегом. Классический пример - тег инфоблока: изменили элемент, сбросился весь кеш, который его показывал.
HTML-кеш - готовая разметка на диске. Так работает кеш меню и, отдельным уровнем, композитный сайт.
Для нового кода приоритет такой: Data\Cache, ManagedCache, TaggedCache.
Классы CPHPCache и менеджер кеша из старого ядра - обёртки над тем же
механизмом, они нужны для правки легаси. И общее правило: кешируют только
производные данные, которые можно безопасно потерять и пересчитать.
Примеры
1. Свой кеш данных
use Bitrix\Main\Data\Cache;
$cache = Cache::createInstance();$cacheTtl = 86400;$cacheId = 'top_products_' . SITE_ID . '_' . $sectionId;$cacheDir = '/catalog/top/' . substr(md5($sectionId), 0, 2);
if ($cache->initCache($cacheTtl, $cacheId, $cacheDir)) { $vars = $cache->getVars(); $items = $vars['items'];} elseif ($cache->startDataCache()) { $items = $this->loadTopProducts($sectionId);
if (empty($items)) { $cache->abortDataCache(); // не кешируем пустой результат return []; }
$cache->endDataCache(['items' => $items]);}Три правила, которые делают этот код правильным:
- В идентификатор кеша включено всё, от чего зависит выборка. Разный вход под одним ключом - это испорченный кеш и трудноуловимые баги.
- Кеш разложен по подпапкам. Одна общая папка на миллион файлов приводит к массовому сбросу при обновлении и переполняет акселератор.
- При ошибке или пустом результате вызывается отмена, а не сохранение частичных данных.
Время жизни ставьте длинным. Час - это обычно слишком мало: кеш будет пересоздаваться чаще, чем приносить пользу. Для управляемого и тегированного кеша нормально ставить неделю и больше, потому что сбросом управляет не время, а события.
2. Кеш компонента
if ($this->startResultCache()) { $this->arResult['ITEMS'] = $this->loadItems();
if (empty($this->arResult['ITEMS'])) { $this->abortResultCache(); return; }
$this->SetResultCacheKeys(['ITEMS']); // в кеш попадёт только это $this->includeComponentTemplate();}Без явного ограничения ключей в кеш уходит весь массив результата целиком. Файл кеша больше мегабайта - верный признак, что кешируется лишнее.
3. Управляемый кеш
$managedCache = \Bitrix\Main\Application::getInstance()->getManagedCache();
if ($managedCache->read(86400 * 30, $cacheKey, 'orm_b_example_item')) { $data = $managedCache->get($cacheKey);} else { $data = $this->calculate(); $managedCache->set($cacheKey, $data);}Порядок здесь строгий: сначала чтение, потом получение или запись. Это не независимое key-value хранилище, и вызов записи без предшествующего чтения некорректен. Третий параметр связывает кеш с таблицей ORM - тогда он сбросится автоматически при изменении данных этой таблицы.
4. Тегированный кеш
$taggedCache = \Bitrix\Main\Application::getInstance()->getTaggedCache();
$taggedCache->startTagCache($cacheDir);$taggedCache->registerTag('my_catalog_prices');$taggedCache->endTagCache();
// при изменении данных$taggedCache->clearByTag('my_catalog_prices');Для инфоблоков теги регистрируются автоматически - но только при включённом
управляемом кеше. Без константы BX_COMP_MANAGED_CACHE регистрация и сброс тегов
молча ничего не делают, и это самая частая причина жалобы «тегированный кеш не
работает».
Вокруг массового импорта теги инфоблока отключают, иначе кеш будет сбрасываться на каждом элементе:
\CIBlock::disableTagCache($iblockId);// массовая загрузка\CIBlock::enableTagCache($iblockId);\CIBlock::clearIblockTagCache($iblockId);Справочник API
| API | Назначение | Особенности |
|---|---|---|
Data\Cache::createInstance() | свой кеш данных | основной способ в новом коде |
initCache() / getVars() | чтение из кеша | |
startDataCache() / endDataCache() | запись в кеш | |
abortDataCache() | отмена записи | при ошибке или пустом результате |
CPHPCache | легаси-аналог | только для правки старого кода |
startResultCache() / abortResultCache() | кеш компонента | внутри - подключение шаблона |
SetResultCacheKeys() | ограничение состава кеша | без него кешируется весь результат |
getManagedCache() | управляемый кеш | порядок: read, затем get или set |
каталог orm_<таблица> | связь кеша с таблицей | даёт автосброс при изменении данных |
getTaggedCache() | тегированный кеш | startTagCache, registerTag, endTagCache |
clearByTag() | сброс по тегу | |
BX_COMP_MANAGED_CACHE | включение управляемого кеша | без неё теги не работают |
disableTagCache() / enableTagCache() | отключение тегов на время импорта | плюс явный сброс после |
sid кеша | разделение кеша между сайтами | уникальный суффикс на сайт или язык |
Частые ошибки
Запись в управляемый кеш без предварительного чтения. Это не независимое хранилище: последовательность вызовов важна.
Управляемый кеш без указания каталога таблицы. Он не будет связан с данными и не сбросится автоматически - придётся чистить руками или ждать истечения времени.
Сохранение частичного результата после ошибки. В кеш попадает невалидное состояние, и оно живёт до истечения времени жизни. Нужна отмена.
Тегированный кеш инфоблоков «не работает». Не включён управляемый кеш.
Кеш перегенерируется на каждом запросе. В идентификатор или в шаблон попали данные, различающиеся между запросами: идентификатор сессии, пользователь, браузер.
Каталог кеша меню разросся до гигабайтов. Кеш меню создаётся на каждую страницу, тип меню и группу пользователей. Выносите тяжёлые запросы из шаблона меню, ограничивайте число файлов настройками компонента и исключайте каталоги кеша из акселератора.
Ручное удаление файлов кеша. Правильный способ - очистка из админки или методы платформы.
Частые вопросы
Какой кеш выбрать для своей выборки?
Если данные меняются редко и допустима задержка - обычный кеш через Data\Cache с длинным временем жизни. Если нужен мгновенный сброс при изменении - управляемый кеш с привязкой к таблице ORM или тегированный кеш с доменным тегом. Если данные меняются постоянно и должны быть всегда актуальными, кеш вообще не нужен: он будет сбрасываться чаще, чем использоваться.
Что должно входить в идентификатор кеша?
Всё, от чего зависит результат: сайт, текущая страница, параметры фильтра, группы пользователя, язык. Правило простое - если при одинаковом ключе возможен разный результат, кеш будет отдавать чужие данные. Обратная крайность тоже вредна: идентификатор сессии или время в ключе делают кеш бесполезным, потому что попаданий не будет никогда.
Почему тегированный кеш не сбрасывается?
Почти всегда потому, что не включён управляемый кеш - без него регистрация тегов и сброс по тегу молча ничего не делают. Проверьте константу в файле подключения к базе или настройку в админке. Вторая причина - тегированный кеш применили к часто меняющимся данным: он формально работает, но сбрасывается почти сразу после создания.
Почему файлы кеша занимают гигабайты?
Обычно виноваты два фактора. Первый - кешируется больше, чем нужно: у компонента не ограничен состав ключей, и в файл уходит весь результат целиком. Второй - высокая вариативность: кеш меню создаётся на каждую страницу, тип меню и группу пользователей, и на большом сайте это сотни тысяч файлов. Лечится ограничением состава кеша, разложением по подпапкам и выносом тяжёлых запросов из шаблонов.
Связанные темы
- Производительность - с чего начинать оптимизацию
- Композитный сайт - HTML-кеш целой страницы
- Компоненты 2.0 - кеш результата компонента
- Сайт тормозит: разбор причин - когда кэш не решает задачу
- Правка не видна на сайте: какой кэш сбросить - разбор по уровням кэша
- Раздел Производительность