Блог разработчика 1С-Битрикс

Виды кеша в Битриксе: руководство с примерами кода

Кеш в Битриксе — это не одна «магическая галочка», а целая система уровней: кеш компонентов, кеш данных (старое ядро и D7), тегированный и управляемый кеш, кеш ORM, HTML/композитный кеш и т.д. Правильное использование каждого вида — это половина оптимизации производительности проекта.

Виды кеша в Битриксе

Ниже — практическое руководство с рабочими примерами кода.

1. Общая карта кешей в Битриксе

Основные виды кеша, с которыми вы сталкиваетесь в реальных проектах:

  1. Кеш компонентов
    • Настраивается в параметрах компонента.
    • Режимы: Авто, Авто + управляемый, Отключ.
  2. PHP-кеш данных
    • Старое ядро — класс CPHPCache.
    • Новое ядро D7 — Bitrix\Main\Data\Cache.
  3. Тегированный (tagged) кеш
    • Позволяет привязать кеш к тегам (например, iblock_id_5), чтобы сбрасывать его при изменении данных.
  4. Управляемый кеш
    • Автоматически сбрасывает кеш компонентов при изменении данных, используется в режиме Авто + управляемый и при ORM-кешировании.
  5. Кеш ORM (D7 ORM)
    • Кеш внутри запросов DataManager::getList() через параметр cache.
  6. HTML/композитный кеш
    • Кеширует целую страницу целиком для анонимных пользователей, используя файловое хранилище /bitrix/html_pages/ и класс StatictmlCache внутри ядра.

Отдельно живут кеши опций, меню, настроек и т.п., но они в основном построены на тех же механизмах (управляемый/тегированный кеш, Data\Cache, ORM).

2. Кеш компонентов: StartResultCache и режимы Авто/Авто+управляемый

2.1. Что кешируется

Компонентный кеш — это сохранение массива $arResult и HTML-вывода шаблона на диск в /bitrix/cache/.

По сути, при включенном кешировании:

  1. Битрикс формирует ID кеша на базе:
    • сайта, имени компонента, шаблона,
    • параметров компонента,
    • «внешних условий» (например, группы пользователя, если вы их учли).
  2. Если такой кеш уже есть и не истёк — просто выводит HTML и $arResult из файла.
  3. Если нет — выполняет код компонента, позаписывает все данные, сохранит их в кеш.

2.2. Пример собственного компонента с кешем

/local/components/vendor/simple.random/class.php:

<?php
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) {
    die();
}
use Bitrix\Main\Loader;
class SimpleRandomComponent extends CBitrixComponent
{
    public function onPrepareComponentParams($params)
    {
        $params['CACHE_TIME'] = (int)$params['CACHE_TIME'] > 0 ? (int)$params['CACHE_TIME'] : 3600;
        $params['CACHE_BY_GROUPS'] = $params['CACHE_BY_GROUPS'] === 'N' ? 'N' : 'Y';
        return $params;
    }
    public function executeComponent()
    {
        global $USER;
        $additionalCacheId = '';
        if ($this->arParams['CACHE_BY_GROUPS'] === 'Y' && is_object($USER)) {
            $additionalCacheId = $USER->GetUserGroupString();
        }
        if ($this->StartResultCache($this->arParams['CACHE_TIME'], $additionalCacheId)) {
            // Здесь можно проверять доступ к данным, модули и т.п.
            if (!Loader::includeModule('iblock')) {
                $this->AbortResultCache();
                ShowError('Модуль "Инфоблоки" не установлен');
                return;
            }
            $this->arResult['RANDOM'] = rand(1, 1000);
            $this->arResult['TIME']   = date('c');
            // Если данные «плохие» — не кешируем
            if ($this->arResult['RANDOM'] < 10) {
                $this->AbortResultCache();
                ShowError('Случайное число меньше 10, кеш не создаётся');
                return;
            }
            $this->IncludeComponentTemplate();
        }
    }
}

/local/components/vendor/simple.random/.parameters.php:

<?php
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) {
    die();
}
$arComponentParameters = [
    'PARAMETERS' => [
        'CACHE_TIME' => [
            'PARENT'  => 'BASE',
            'NAME'    => 'Время кеширования (сек)',
            'TYPE'    => 'STRING',
            'DEFAULT' => 3600,
        ],
        'CACHE_BY_GROUPS' => [
            'PARENT'  => 'CACHE_SETTINGS',
            'NAME'    => 'Разделять кеш по группам пользователей',
            'TYPE'    => 'CHECKBOX',
            'DEFAULT' => 'Y',
        ],
    ],
];

Шаблон компонента /local/components/vendor/simple.random/templates/.default/template.php:

<?php if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) die(); ?>
<div class="simple-random">
    <div>Случайное число: <?= (int)$arResult['RANDOM']; ?></div>
    <div>Сформировано: <?= htmlspecialcharsbx($arResult['TIME']); ?></div>
</div>

Режим кеширования (Авто / Авто+управляемый) задаётся уже в настройках компонента в визуальном редакторе.

3. Кеш данных старого ядра: CPHPCache

CPHPCache — класс старого ядра, который умеет кешировать массивы переменных и HTML-вывод в файловой системе (/bitrix/cache/).

3.1. Базовый пример CPHPCache

<?php
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) {
    die();
}
/** @var CMain $APPLICATION */
$cacheTime = 3600;
$cacheId   = 'demo_cphpcache_example';
$cacheDir  = '/demo/cphpcache';
$cache = new CPHPCache();
$data  = [];
if ($cache->InitCache($cacheTime, $cacheId, $cacheDir)) {
    // Читаем данные из кеша
    $data = $cache->GetVars();
} elseif ($cache->StartDataCache()) {
    // Эмулируем тяжёлую операцию
    $data = [
        'TIME'    => date('c'),
        'RANDOM'  => rand(100, 999),
        'MESSAGE' => 'Данные сгенерированы без кеша',
    ];
    // Проверка условия, при котором кеш не нужен
    if ($data['RANDOM'] < 150) {
        $cache->AbortDataCache();
    } else {
        $cache->EndDataCache($data);
    }
}
// Выводим результат
echo '<pre>';
print_r($data);
echo '</pre>';

Важно:

  • InitCache() — проверяет наличие и актуальность кеша.
  • StartDataCache() — либо начинает буферизацию, либо сразу выводит кеш и возвращает false.
  • EndDataCache($vars) — сохраняет данные.
  • AbortDataCache() — отмена сохранения кеша.

4. D7 кеш данных: Bitrix\Main\Data\Cache

Современный D7-класс Bitrix\Main\Data\Cache работает почти так же, как CPHPCache, но лучше вписывается в D7-код и поддерживает дополнительные возможности (управление из кода, динамические конфиги и т.п.).

4.1. Простой пример с Bitrix\Main\Data\Cache

<?php
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) {
    die();
}
use Bitrix\Main\Data\Cache;
$cacheTime = 3600;
$cacheId   = 'demo_d7_cache_example';
$cacheDir  = '/demo/d7_cache';
$cache = Cache::createInstance();
$data  = [];
if ($cache->initCache($cacheTime, $cacheId, $cacheDir)) {
    $data = $cache->getVars();
} elseif ($cache->startDataCache()) {
    $data = [
        'TIME'    => date('c'),
        'RANDOM'  => rand(1, 1000),
        'MESSAGE' => 'Сформировано с использованием D7 Cache',
    ];
    if ($data['RANDOM'] === 777) {
        // Вдруг нам не нравится это число :)
        $cache->abortDataCache();
    } else {
        $cache->endDataCache($data);
    }
}
echo '<pre>';
print_r($data);
echo '</pre>';

4.2. Пример кеширования тяжёлого запроса к инфоблоку на D7

<?php
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) {
    die();
}
use Bitrix\Main\Data\Cache;
use Bitrix\Main\Loader;
$iblockId = 5;
$cacheTime = 600;
$cacheId   = 'iblock_' . $iblockId . '_top5';
$cacheDir  = '/demo/iblock_top5';
$cache = Cache::createInstance();
$arResult = [
    'ITEMS' => [],
];
if ($cache->initCache($cacheTime, $cacheId, $cacheDir)) {
    $arResult = $cache->getVars();
} elseif ($cache->startDataCache()) {
    if (!Loader::includeModule('iblock')) {
        $cache->abortDataCache();
    } else {
        $res = CIBlockElement::GetList(
            ['ACTIVE_FROM' => 'DESC'],
            [
                'IBLOCK_ID' => $iblockId,
                'ACTIVE'    => 'Y',
            ],
            false,
            ['nTopCount' => 5],
            ['ID', 'NAME', 'DETAIL_PAGE_URL', 'ACTIVE_FROM']
        );
        while ($item = $res->GetNext()) {
            $arResult['ITEMS'][] = $item;
        }
        if (empty($arResult['ITEMS'])) {
            $cache->abortDataCache();
        } else {
            $cache->endDataCache($arResult);
        }
    }
}
if (!empty($arResult['ITEMS'])) {
    echo '<ul>';
    foreach ($arResult['ITEMS'] as $item) {
        echo '<li>';
        echo '<a href="' . htmlspecialcharsbx($item['DETAIL_PAGE_URL']) . '">';
        echo htmlspecialcharsbx($item['NAME']);
        echo '</a>';
        if (!empty($item['ACTIVE_FROM'])) {
            echo ' (' . htmlspecialcharsbx($item['ACTIVE_FROM']) . ')';
        }
        echo '</li>';
    }
    echo '</ul>';
}

5. Тегированный кеш и управляемый кеш

5.1. Идея тегированного кеша

Тегированный кеш (Tagged Cache) позволяет «подписать» кеш тегами (например, iblock_id_5), а при изменении данных ядро Битрикс сбрасывает все кеши, связанные с этим тегом.

Это основа управляемого кеша — именно поэтому в режиме Авто + управляемый кеш компонентов обновляется сразу после изменения инфоблока, меню и т.п.

5.2. Пример: тегированный кеш списка новостей инфоблока

<?php
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) {
    die();
}
use Bitrix\Main\Application;
use Bitrix\Main\Data\Cache;
use Bitrix\Main\Loader;
$iblockId  = 5;
$cacheTime = 3600;
$cacheId   = 'news_list_iblock_' . $iblockId;
$cacheDir  = '/demo/tagged_news_list';
$cache        = Cache::createInstance();
$taggedCache  = Application::getInstance()->getTaggedCache();
$arResult     = [
    'ITEMS' => [],
];
if ($cache->initCache($cacheTime, $cacheId, $cacheDir)) {
    $arResult = $cache->getVars();
} elseif ($cache->startDataCache()) {
    if (!Loader::includeModule('iblock')) {
        $cache->abortDataCache();
    } else {
        $taggedCache->startTagCache($cacheDir);
        // Привязываем кеш ко всему инфоблоку
        $taggedCache->registerTag('iblock_id_' . $iblockId);
        $res = CIBlockElement::GetList(
            ['ACTIVE_FROM' => 'DESC'],
            [
                'IBLOCK_ID' => $iblockId,
                'ACTIVE'    => 'Y',
            ],
            false,
            ['nTopCount' => 10],
            ['ID', 'NAME', 'DETAIL_PAGE_URL', 'ACTIVE_FROM']
        );
        while ($item = $res->GetNext()) {
            $arResult['ITEMS'][] = $item;
        }
        if (empty($arResult['ITEMS'])) {
            $taggedCache->abortTagCache();
            $cache->abortDataCache();
        } else {
            $taggedCache->endTagCache();
            $cache->endDataCache($arResult);
        }
    }
}
if (!empty($arResult['ITEMS'])) {
    echo '<ul>';
    foreach ($arResult['ITEMS'] as $item) {
        echo '<li>';
        echo '<a href="' . htmlspecialcharsbx($item['DETAIL_PAGE_URL']) . '">';
        echo htmlspecialcharsbx($item['NAME']);
        echo '</a>';
        if (!empty($item['ACTIVE_FROM'])) {
            echo ' (' . htmlspecialcharsbx($item['ACTIVE_FROM']) . ')';
        }
        echo '</li>';
    }
    echo '</ul>';
}

Когда вы добавите/измените/удалите элементы в инфоблоке $iblockId, ядро запустит механизм сброса тегированного кеша по тегу iblock_id_{$iblockId}, и ваш кеш пересоздастся.

5.3. Управляемый кеш через Application::getInstance()->getManagedCache()

Управляемый кеш (ManagedCache) в D7 можно получить так:

<?php
use Bitrix\Main\Application;
/** @var \Bitrix\Main\Data\ManagedCache $managedCache */
$managedCache = Application::getInstance()->getManagedCache();

У него есть методы read, get, set, clean. Пример ручного кеша настроек (вместо частых запросов к БД):

<?php
use Bitrix\Main\Application;
use Bitrix\Main\Data\ManagedCache;
use Bitrix\Main\Loader;
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) {
    die();
}
/** @var ManagedCache $managedCache */
$managedCache = Application::getInstance()->getManagedCache();
$cacheTime = 3600;
$cacheId   = 'custom_settings_demo';
if ($managedCache->read($cacheTime, $cacheId)) {
    $settings = $managedCache->get($cacheId);
} else {
    $settings = [];
    if (Loader::includeModule('main')) {
        // Здесь вы могли бы считать свои настройки из БД, HL-блока и т.п.
        $settings = [
            'ENABLE_FEATURE' => 'Y',
            'MAX_ITEMS'      => 20,
        ];
    }
    $managedCache->set($cacheId, $settings);
}
echo '<pre>';
print_r($settings);
echo '</pre>';

Очистить такой кеш можно, например, при сохранении настроек:

<?php
use Bitrix\Main\Application;
$managedCache = Application::getInstance()->getManagedCache();
$managedCache->clean('custom_settings_demo');

6. Кеш ORM (D7 ORM cache)

ORM-запросы в Битрикс D7 поддерживают встроенный кеш через ключ cache в параметрах getList() / getRow().

6.1. Пример кеша ORM-запроса

<?php
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) {
    die();
}
use Bitrix\Main\Loader;
use Bitrix\Main\UserTable;
if (!Loader::includeModule('main')) {
    ShowError('Модуль "main" не найден');
    return;
}
$result = UserTable::getList([
    'select' => ['ID', 'LOGIN', 'NAME', 'LAST_NAME'],
    'filter' => [
        '=ACTIVE' => 'Y',
    ],
    'order' => [
        'ID' => 'ASC',
    ],
    'limit' => 50,
    'cache' => [
        'ttl'         => 600,    // Время жизни кеша в секундах
        'cache_joins' => true,   // Кешировать ли запросы с JOIN'ами
    ],
]);
$users = [];
while ($user = $result->fetch()) {
    $users[] = $user;
}
echo '<pre>';
print_r($users);
echo '</pre>';

По умолчанию для ORM можно задать глобальные TTL и поведение кеша через параметр cache_flags в /bitrix/.settings.php, где управляемый кеш используется как хранилище.

7. HTML-кеш и композитный сайт

HTML-кеш (статический кеш страниц) — это кеширование полностью собранного HTML-ответа. В Битриксе композитный режим опирается на класс StaticHtmlCache, который пишет данные в файловую систему и, при необходимости, в Memcached. Разработчики обычно не используют этот класс напрямую — всё управляется из настроек и через API композитного сайта.

Файлы HTML-кеша живут в /bitrix/html_pages/.

7.1. Динамические области в шаблонах (композитный сайт)

Чтобы часть страницы не попадала в HTML-кеш, используются динамические области (frame):

<?php if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) die(); ?>
<div class="header-cart">
    <?php
    /** @var CBitrixComponentTemplate $this */
    $frame = $this->createFrame()->begin();
    ?>
        <span class="header-cart__count">
            <?= (int)$arResult['CART_COUNT']; ?>
        </span>
    <?php
    $frame->beginStub();
    ?>
        <span class="header-cart__count">0</span>
    <?php
    $frame->end();
    ?>
</div>
  • Всё, что внутри begin() / end() — подгружается динамически (ajax-фрагмент).
  • beginStub() — что увидит пользователь до загрузки динамической части.

8. Где физически лежит кеш

Полезно понимать, что и куда пишет Битрикс:

  • /bitrix/cache/
    • Некачируемый (unmanaged) кеш, кеш компонентов, Data\Cache, CPHPCache по умолчанию.
  • /bitrix/managed_cache/
    • Управляемый кеш (ManagedCache), кеш ORM, кеш различных системных сущностей.
  • /bitrix/html_pages/
    • HTML-/композитный кеш страниц.
  • Папки вида /bitrix/managed_cache/MYSQL/orm_%имя_таблицы%/
    • ORM-кеш по SQL-запросам (ключ — md5(sql)).

9. Какой кеш когда использовать

Коротко:

  • Компонентный кеш
    • Для всего, что выводится через компоненты (каталог, новости, списки и т.п.).
    • Всегда включайте режим Авто + управляемый, если данные меняются относительно редко, а производительность важна.
  • CPHPCache / Data\Cache
    • Для сложных кастомных выборок, сниппетов в шаблонах, старого кода.
    • На новых проектах используйте Bitrix\Main\Data\Cache.
  • Тегированный + ManagedCache
    • Когда нужно умно сбрасывать кеш по изменениям данных: инфоблоки, HL-блоки, собственные сущности.
  • ORM cache
    • Для повторяющихся тяжёлых ORM-запросов, где вы не хотите вручную управлять ID кеша.
  • HTML/композит
    • Для публичной части сайта, где много анонимного трафика; особенно для страниц с тяжёлым рендером.

10. Практические советы и анти-паттерны

  1. Не ставьте слишком короткий TTL, если используете управляемый кеш.

    Для режима Авто + управляемый можно ставить большие значения TTL (до года), потому что кеш сбрасывается не по времени, а по событию изменения данных.

  2. Формируйте cacheId из всех параметров, влияющих на результат.

    Это касается и CPHPCache/Data\Cache, и компонентного кеша (дополнительный ID).

  3. Не кешируйте то, что зависит от пользователя, без разделения по группам или ID.

    Например, корзина, личный кабинет — либо не кешируются, либо кешируются с учётом ID пользователя.

  4. Всегда предусмотрите возможность сбросить кеш программно.

    Например, отдельный админский обработчик, который вызывает clean, cleanDir, clearCache для нужных путей.

  5. Следите за размером /bitrix/cache/ и /bitrix/managed_cache/.

    При неправильной стратегии TTL и агрессивном кешировании эти каталоги могут разрастаться на гигабайты.

Теги: кэш, кеширование, компонентный кеш, тегированный кеш, управляемый кеш, ORM кеш, HTML кеш, композитный сайт, cache, caching, performance, optimization, D7, CPHPCache, Bitrix\Main\Data\Cache


Валерий Макеев
30.11.2025 12:30
1. Базовый шаблон Bitrix\Main\Data\Cache

Сценарий: кешируем любой тяжёлый набор данных (запросы в БД, API и т.д.).

Код
<?php

use Bitrix\Main\Data\Cache;

if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) {
    die();
}

$cacheTime = 3600;                            // TTL кеша в секундах
$cacheId   = 'demo_simple_cache';             // Уникальный ID кеша
$cacheDir  = '/demo/simple_cache';            // Папка внутри /bitrix/cache

$cache = Cache::createInstance();
$result = [];

// 1. Пытаемся прочитать кеш
if ($cache->initCache($cacheTime, $cacheId, $cacheDir)) {
    $result = $cache->getVars();
}
// 2. Кеша нет — генерируем данные и пишем в кеш
elseif ($cache->startDataCache()) {

    // Здесь ваша «тяжёлая» логика
    $result = [
        'TIME'   => date('c'),
        'VALUE1' => rand(1, 100),
        'VALUE2' => rand(100, 999),
    ];

    // Проверка: если результат «плохой» — не кешируем
    $needAbort = ($result['VALUE1'] < 10);

    if ($needAbort) {
        $cache->abortDataCache();            // НЕ создаём кеш
    } else {
        $cache->endDataCache($result);       // Сохраняем данные в кеш
    }
}

// Используем результат
echo '<pre>';
print_r($result);
echo '</pre>';

Стоимость услуг по разработке и сопровождению сайтов на 1C-Битрикс

Разработка корпоративного сайта

от 7 дней

от 40 000 рублей

Разработка сайта без системы оплаты заказов через корзину

* стоимость зависит от наличия верстки, использования готового решения и т.д.

Лечение сайтов от вирусов

восстановление сайта и подъем версии PHP

от 25 000 рублей
Лечение сайтов на решениях АСПРО и прочих.

* полный комплекс лечения проекта и закрытия дыр

Модули и компоненты для «1С-Битрикс»

оценка производится на основе предоставленного Технического Задания

от 20 000 рублей
Разработка дополнительных модулей для 1С-Битрикс, расширение функционала, внедрение любых решений, требующихся для выполнения ваших бизнес-задач.

* стоимость зависит от конкретной задачи, ее объема и сложности выполняемых работ.