Ускорение работы сайта через механизмы кэширования в Битриксе
Кэширование в Bitrix: варианты реализации и оптимизация
Как добиться максимальной производительности с тегированным кэшем?
Рекомендуемое решение: Bitrix\Main\Data\Cache с тегами и временем жизни.
use Bitrix\Main\Data\Cache;
$cache = Cache::createInstance();
$cacheTime = 3600; // 1 час
$cacheId = 'my_custom_data';
$cachePath = '/my_module/';
if ($cache->initCache($cacheTime, $cacheId, $cachePath)) {
$result = $cache->getVars();
} else {
// Генерация данных
$data = [];
\Bitrix\Main\Loader::includeModule('iblock');
$elements = \Bitrix\Iblock\ElementTable::getList([
'filter' => ['IBLOCK_ID' => 1, 'ACTIVE' => 'Y'],
'select' => ['ID', 'NAME'],
'limit' => 100
])->fetchAll();
foreach ($elements as $el) {
$data[$el['ID']] = $el['NAME'];
}
$cache->startDataCache();
$cache->endDataCache($data);
$result = $data;
}
// Использование $result
Php http cache (http-кэширование в php)
Типичные ошибки:
- Не очищается кэш после изменения данных. Решение: использовать теги для автоматической очистки через $cache->registerTag('iblock_id_1').
- Ключ кэша не уникален – данные разных пользователей смешиваются. Решение: добавлять в $cacheId контекст (язык, сайт, группа пользователя).
- Переполнение файлового кэша. Решение: ограничить время жизни или использовать внешние хранилища (memcached/redis).
Цель: кэширование результатов сложных SQL-запросов, вычислений, данных, которые редко изменяются.
Как закэшировать результат простого запроса с помощью CPHPCache?
$obCache = new CPHPCache();
$cacheTime = 86400; // 24 часа
$cacheId = 'simple_data_' . SITE_ID;
$cachePath = '/simple/';
if ($obCache->InitCache($cacheTime, $cacheId, $cachePath)) {
$result = $obCache->GetVars();
} else {
// Формирование данных
$result = ['time' => time(), 'text' => 'some heavy operation'];
if ($obCache->StartDataCache()) {
$obCache->EndDataCache($result);
}
}
Wp content object cache php (кэш объектов в wp-content (wordpress))
Проблема: отсутствие автоматической очистки при изменении данных. Приходится вручную вызывать CPHPCache::ClearCache($cacheId, $cachePath).
Как кэшировать HTML-вывод компонента для неавторизованных пользователей?
Используется технология композитного кэширования (Bitrix Composite Cache). Настройка в файле .settings.php:
'cache' => [
'type' => [
'class' => '\\Bitrix\\Main\\Data\\CacheEngineFiles',
'use_cluster' => false
],
'html' => [
'ttl' => 3600
]
]
Bitrix php cache (кэширование в bitrix (php))
Включить опцию "Кэшировать для гостей" в настройках компонента. Результат – статический HTML отдается без выполнения PHP.
Ошибки: компоненты с динамическими данными (корзина, личный кабинет) требуют исключения из кэша через параметр COMPOSITE_FRAME_MODE.
Как использовать memcached для внешнего кэша?
// .settings.php
'cache' => [
'type' => [
'class' => '\\Bitrix\\Main\\Data\\CacheEngineMemcache',
'servers' => [
[
'host' => '127.0.0.1',
'port' => '11211'
]
]
]
]
После настройки все кэширование автоматически переключается на memcached. Ускоряет доступ и снимает нагрузку с файловой системы.
Требуется установленное расширение PHP memcached. Необходимо следить за объемом памяти в memcached – при переполнении ключи удаляются.
Расширенные примеры кэширования с детальными пояснениями
Пример 1. Кэширование с тегами и автоматической очисткой при обновлении инфоблока
use Bitrix\Main\Data\Cache;
use Bitrix\Iblock\ElementTable;
$cache = Cache::createInstance();
$ttl = 7200;
$cacheId = 'iblock_elements_' . SITE_ID . '_' . LANGUAGE_ID;
$cachePath = '/iblock_data/';
if ($cache->initCache($ttl, $cacheId, $cachePath)) {
$elements = $cache->getVars();
} else {
$elements = [];
$rs = ElementTable::getList([
'filter' => ['IBLOCK_ID' => 2, 'ACTIVE' => 'Y'],
'select' => ['ID', 'NAME', 'CODE', 'TIMESTAMP_X'],
'order' => ['SORT' => 'ASC']
]);
while ($el = $rs->fetch()) {
$elements[$el['ID']] = [
'name' => $el['NAME'],
'code' => $el['CODE'],
'date' => $el['TIMESTAMP_X']->toString()
];
}
$cache->startDataCache();
$cache->registerTag('iblock_id_' . 2); // тег по инфоблоку
// Можно добавить теги для каждого элемента
foreach (array_keys($elements) as $id) {
$cache->registerTag('iblock_element_' . $id);
}
$cache->endDataCache($elements);
}
// Вывод
foreach ($elements as $id => $data) {
echo "{$data['name']} ({$data['code']}) - {$data['date']}\n";
}
Результат: Товар1 (tovar1) - 2025-03-28 14:22:10 Товар2 (tovar2) - 2025-03-28 16:05:33 ...
Пояснение: при изменении элемента инфоблока метод CIBlockElement::SetPropertyValues (и другие) вызывает очистку всех кэшей с соответствующими тегами.
Пример 2. Кэширование результатов вызова внешнего API
use Bitrix\Main\Data\Cache;
function getCurrencyRates() {
$cache = Cache::createInstance();
$ttl = 1800; // 30 минут
$cacheId = 'currency_rates_' . SITE_ID;
$cachePath = '/currency/';
if ($cache->initCache($ttl, $cacheId, $cachePath)) {
return $cache->getVars();
} else {
$url = 'https://api.exchangerate-api.com/v4/latest/USD';
$response = file_get_contents($url);
if ($response === false) {
// вернуть устаревшие данные или заглушку
return false;
}
$data = json_decode($response, true);
$rates = $data['rates'];
$cache->startDataCache();
$cache->endDataCache($rates);
return $rates;
}
}
$rates = getCurrencyRates();
print_r($rates);
Результат:
Array
(
[AED] => 3.6732
[AFN] => 77.5
[ALL] => 103.85
...
)Пояснение: кэширование защищает от повторных запросов к внешнему API в случае временной недоступности (возвращается кэш). Установлен короткий TTL для актуальности курсов.
Пример 3. Кэширование сложных вычислений с привязкой к пользователю
$userId = \Bitrix\Main\Engine\CurrentUser::get()->getId();
$cacheId = 'user_dashboard_' . $userId;
$cachePath = '/dashboard/';
$cache = Cache::createInstance();
if ($cache->initCache(300, $cacheId, $cachePath)) {
$dashboard = $cache->getVars();
} else {
// Вычисления: количество заказов, любимые категории и т.д.
$dashboard = [
'orders_count' => getOrdersCount($userId),
'favorite_categories' => getFavCategories($userId),
'last_order_date' => getLastOrderDate($userId)
];
$cache->startDataCache();
// Можно добавить теги для очистки при изменении заказов пользователя
$cache->registerTag('user_' . $userId);
$cache->endDataCache($dashboard);
}
return $dashboard;
Важно: при изменении данных пользователя (оформление заказа) очистить кэш по тегу user_N. Например, в обработчике события OnSaleOrderSaved вызывать \Bitrix\Main\Data\Cache::clearCacheByTag('user_' . $userId).