Что надо знать о кеше в Битриксе.

Внимание! Работает режим премодерации. Все сообщения публикуются после проверки!
Страницы: 1
Ответить
RSS
Что надо знать о кеше в Битриксе.
Виды кеша в Битриксе: руководство с примерами кода

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

Ниже будет еще 7-8 примеров с пояснениями ↓
Изменено: Валерий Макеев - 30.11.2025 12:40:33
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>';
2. Универсальный хелпер cacheRemember()

Идея: один раз написали функцию — дальше кешируете всё одной строкой.

Код
<?php

use Bitrix\Main\Data\Cache;

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

/**
 * Обёртка над Bitrix\Main\Data\Cache.
 *
 * @param int      $ttl         Время жизни кеша (секунды)
 * @param string   $cacheId     Уникальный ID кеша (без пути)
 * @param string   $cacheDir    Каталог кеша (с ведущим слешем)
 * @param callable $callback    Функция, которая вернёт данные для кеша
 *
 * @return mixed
 */
function cacheRemember(int $ttl, string $cacheId, string $cacheDir, callable $callback)
{
    $cache  = Cache::createInstance();
    $result = null;

    if ($cache->initCache($ttl, $cacheId, $cacheDir)) {
        $result = $cache->getVars();
    } elseif ($cache->startDataCache()) {
        $result = call_user_func($callback);

        // Если коллбек вернул null — не кешируем
        if ($result === null) {
            $cache->abortDataCache();
        } else {
            $cache->endDataCache($result);
        }
    }

    return $result;
}

// ПРИМЕР ИСПОЛЬЗОВАНИЯ:
// Кешируем список из БД, API и т.п.

$users = cacheRemember(
    600,
    'active_users_v1',
    '/demo/users',
    static function () {
        // Здесь можно сделать произвольный код
        // Пример — просто сгенерим массив
        $list = [];
        for ($i = 1; $i <= 5; $i++) {
            $list[] = [
                'ID'   => $i,
                'NAME' => 'User ' . $i,
            ];
        }

        // Если хотите не кешировать — верните null
        // return null;

        return $list;
    }
);

echo '<pre>';
print_r($users);
echo '</pre>';
3. Кеширование выборки инфоблока через Data\Cache

Сценарий: тяжёлая выборка CIBlockElement::GetList, которую хочется кешировать.

Код
<?php

use Bitrix\Main\Data\Cache;
use Bitrix\Main\Loader;

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

$iblockId  = 5;
$limit     = 10;
$cacheTime = 900;

// Формируем ID кеша из параметров
$cacheId  = 'iblock_' . $iblockId . '_top_' . $limit;
$cacheDir = '/demo/iblock_top';

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

if ($cache->initCache($cacheTime, $cacheId, $cacheDir)) {
    $arItems = $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' => $limit],
            ['ID', 'NAME', 'DETAIL_PAGE_URL', 'ACTIVE_FROM']
        );

        while ($row = $res->GetNext()) {
            $arItems[] = $row;
        }

        // Если ничего не нашли — не создаём кеш
        if (empty($arItems)) {
            $cache->abortDataCache();
        } else {
            $cache->endDataCache($arItems);
        }
    }
}

if (!empty($arItems)) {
    echo '<ul>';
    foreach ($arItems 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>';
}
4. Базовый шаблон TaggedCache + Data\Cache

Сценарий: кешируем произвольные данные и вешаем на них теги, чтобы потом сбросить по тегу.
TaggedCache берётся из Application::getInstance()->getTaggedCache().

Код
<?php

use Bitrix\Main\Application;
use Bitrix\Main\Data\Cache;

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

$cacheTime = 86400;
$cacheId   = 'tagged_demo_cache';
$cacheDir  = '/demo/tagged_cache';

// 1. Службы кеша и тегов
$cache       = Cache::createInstance();
$taggedCache = Application::getInstance()->getTaggedCache();

$data = [];

if ($cache->initCache($cacheTime, $cacheId, $cacheDir)) {
    $data = $cache->getVars();
} elseif ($cache->startDataCache()) {

    // 2. Начинаем тегированный кеш (путь должен совпадать с $cacheDir)
    $taggedCache->startTagCache($cacheDir);

    // 3. Регистрируем один или несколько тегов
    $taggedCache->registerTag('my_custom_tag');
    $taggedCache->registerTag('my_second_tag');

    // 4. Формируем данные
    $data = [
        'TIME'   => date('c'),
        'VALUE1' => rand(1, 100),
        'VALUE2' => rand(1000, 9999),
    ];

    $needAbort = ($data['VALUE1'] < 20);

    if ($needAbort) {
        // Если кеш не нужен — отменяем и теги, и данные
        $taggedCache->abortTagCache();
        $cache->abortDataCache();
    } else {
        // Всё хорошо — закрываем тегированный кеш и сохраняем данные
        $taggedCache->endTagCache();
        $cache->endDataCache($data);
    }
}

echo '<pre>';
print_r($data);
echo '</pre>';
5. TaggedCache + инфоблок: кеш обновляется при изменении инфоблока

Сценарий: список элементов инфоблока, который должен автоматически обновляться при добавлении/изменении/удалении элементов или свойств.
Для этого привязываем кеш к тегу вида iblock_id_{$iblockId} — именно по нему Битрикс сбрасывает тегированный кеш.

Код
<?php

use Bitrix\Main\Application;
use Bitrix\Main\Data\Cache;
use Bitrix\Main\Loader;

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

$iblockId  = 7;
$limit     = 5;
$cacheTime = 3600;

$cacheId  = 'iblock_' . $iblockId . '_tagged_' . $limit;
$cacheDir = '/demo/iblock_tagged_list';

$cache       = Cache::createInstance();
$taggedCache = Application::getInstance()->getTaggedCache();

$arItems = [];

if ($cache->initCache($cacheTime, $cacheId, $cacheDir)) {
    $arItems = $cache->getVars();
} elseif ($cache->startDataCache()) {

    if (!Loader::includeModule('iblock')) {
        $taggedCache->abortTagCache();
        $cache->abortDataCache();
    } else {
        // Стартуем тегированный кеш обязательно с тем же путём, что и $cacheDir
        $taggedCache->startTagCache($cacheDir);

        // Привязываем кеш к целому инфоблоку
        $taggedCache->registerTag('iblock_id_' . $iblockId);

        $res = CIBlockElement::GetList(
            ['ACTIVE_FROM' => 'DESC'],
            [
                'IBLOCK_ID' => $iblockId,
                'ACTIVE'    => 'Y',
            ],
            false,
            ['nTopCount' => $limit],
            ['ID', 'NAME', 'DETAIL_PAGE_URL', 'ACTIVE_FROM']
        );

        while ($row = $res->GetNext()) {
            $arItems[] = $row;
        }

        if (empty($arItems)) {
            $taggedCache->abortTagCache();
            $cache->abortDataCache();
        } else {
            // Закрываем тегированный кеш и сохраняем данные
            $taggedCache->endTagCache();
            $cache->endDataCache($arItems);
        }
    }
}

// Выводим, как обычно
if (!empty($arItems)) {
    echo '<ul>';
    foreach ($arItems 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>';
}

Теперь, когда что-то меняется в инфоблоке ID = 7, Битрикс сам сбросит весь кеш, помеченный тегом iblock_id_7, и на следующем хите он пересоздастся.
6. Очистка кеша: по ключу, по каталогу, по тегу

6.1. Очистка Data\Cache по конкретному ключу
Код
<?php

use Bitrix\Main\Data\Cache;

$cache   = Cache::createInstance();
$cacheId = 'demo_simple_cache';
$cacheDir = '/demo/simple_cache';

// Полностью удалить один кеш по ключу
$cache->clean($cacheId, $cacheDir);


Метод clean() соответствует uniqueString + initDir, как в initCache().

6.2. Очистка всей папки кеша
Код
<?php

use Bitrix\Main\Data\Cache;

$cacheDir = '/demo/simple_cache';

// Удалить ВСЕ кеши внутри этого каталога
$cache = Cache::createInstance();
$cache->cleanDir($cacheDir);

// Либо статически (устаревший, но встречается в коде)
Cache::clearCache(true, $cacheDir);


6.3. Очистка тегированного кеша по тегу
Код
<?php

use Bitrix\Main\Application;

// В любом месте, где нужен сброс по тегу:
$taggedCache = Application::getInstance()->getTaggedCache();

// Сбросить всё, что помечено этим тегом
$taggedCache->clearByTag('my_custom_tag');

// Примеры для инфоблоков:
$iblockId = 7;
$taggedCache->clearByTag('iblock_id_' . $iblockId);


clearByTag() — основной метод TaggedCache для ручного сброса кеша по тегу.
7. Хелпер для TaggedCache «кешируй с тегом»

Сценарий: хотите каждый раз не копировать блок с startTagCache/registerTag/endTagCache.

Код
<?php

use Bitrix\Main\Application;
use Bitrix\Main\Data\Cache;

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

/**
 * Кеширование с TaggedCache.
 *
 * @param int      $ttl
 * @param string   $cacheId
 * @param string   $cacheDir
 * @param array    $tags      Список тегов для кеша
 * @param callable $callback  Возвращает данные для кеша
 *
 * @return mixed
 */
function taggedCacheRemember(int $ttl, string $cacheId, string $cacheDir, array $tags, callable $callback)
{
    $cache       = Cache::createInstance();
    $taggedCache = Application::getInstance()->getTaggedCache();

    $result = null;

    if ($cache->initCache($ttl, $cacheId, $cacheDir)) {
        $result = $cache->getVars();
    } elseif ($cache->startDataCache()) {

        $taggedCache->startTagCache($cacheDir);

        foreach ($tags as $tag) {
            $taggedCache->registerTag((string)$tag);
        }

        $result = call_user_func($callback);

        if ($result === null) {
            $taggedCache->abortTagCache();
            $cache->abortDataCache();
        } else {
            $taggedCache->endTagCache();
            $cache->endDataCache($result);
        }
    }

    return $result;
}

// ПРИМЕР ИСПОЛЬЗОВАНИЯ:
// Кешируем список товаров инфоблока с автоматическим сбросом по инфоблоку и кастомному тегу.

$iblockId = 10;

$products = taggedCacheRemember(
    3600,
    'products_iblock_' . $iblockId,
    '/demo/products_tagged',
    [
        'iblock_id_' . $iblockId,
        'my_custom_tag_products',
    ],
    static function () use ($iblockId) {
        if (!\Bitrix\Main\Loader::includeModule('iblock')) {
            return null;
        }

        $items = [];

        $res = CIBlockElement::GetList(
            ['SORT' => 'ASC'],
            [
                'IBLOCK_ID' => $iblockId,
                'ACTIVE'    => 'Y',
            ],
            false,
            false,
            ['ID', 'NAME']
        );

        while ($row = $res->GetNext()) {
            $items[] = $row;
        }

        if (empty($items)) {
            return null;
        }

        return $items;
    }
);

echo '<pre>';
print_r($products);
echo '</pre>';
8. Мини-заметки, чтобы не словить грабли
  1. $cacheDir обязательно должен начинаться со слеша (/demo/cache). Это важно и для файлового кеша, и для Memcache/APC.
  2. Для тегированного кеша путь в startTagCache($cacheDir) должен совпадать с initCache(..., $cacheDir).
  3. Если отменяете кеш внутри блока с тегами — вызывайте оба метода:
    abortTagCache() и abortDataCache().
  4. TTL можно ставить большим (до дней/недель), если привязываетесь к тегам и сбрасываете кеш по событиям, а не по времени.
Страницы: 1
Ответить
Форма ответов
Текст сообщения*
Перетащите файлы
Ничего не найдено
Файл
 

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

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

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

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

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

Перенос сайтов на «1С-Битрикс»

сайты на платформе «1С-Битрикс» — это удобство, надежность и высокая посещаемость

от 12 000 рублей
Перенос сайтов с любых CMS и статичных страниц на платформу «1С-Битрикс», с учетом дизайна, верстки и урл-адресов. С сохранением всей информации и структуры сайта.

* зависит от объема выполняемых работ.

Участие в проекте

привлечение в проект на part-time основе

от 30 000 рублей / неделя

Возможно участие в проекте на ежедневной основе, как разработчика. Занятость - до 20 часов в неделю
Минимальный срок - одна неделя.

* сумма фиксированная