Розробка модуля кешування 1С-Бітрікс
У Бітрікс є власний кеш через \Bitrix\Main\Data\Cache — файловий, з підтримкою тегів через \Bitrix\Main\Data\TaggedCache. На невеликих сайтах він працює нормально. Проблеми починаються при високому навантаженні: тисячі файлів у /bitrix/cache/, операції читання/запису конкурують на файловій системі, інвалідація за тегом — блокуюча операція. Модуль кешування надбудовує над стандартним механізмом єдиний шар з Redis-бекендом, статистикою, прогрівом та гранулярною інвалідацією.
Архітектура: CacheManager
Центральний клас CacheManager реалізує патерн стратегії. Бекенд обирається в налаштуваннях модуля:
$cache = \Vendor\Cache\CacheManager::getInstance();
// Стандартний get-or-set
$result = $cache->remember('catalog_section_12', 3600, function() {
return CIBlockSection::GetList(/* ... */)->Fetch();
}, ['iblock_12', 'catalog']);
// → Дані з кешу або результат callable при промаху
// Явна інвалідація за тегом
$cache->invalidateTag('iblock_12');
// → Скидаються всі ключі, позначені тегом iblock_12
Redis-бекенд
Файловий кеш Бітрікс не масштабується на кілька серверів. Redis вирішує цю проблему:
class RedisCacheBackend implements CacheBackendInterface
{
private \Redis $redis;
public function get(string $key): mixed
{
$data = $this->redis->get($key);
return $data !== false ? unserialize($data) : null;
}
public function set(string $key, mixed $value, int $ttl, array $tags = []): void
{
$serialized = serialize($value);
$this->redis->setEx($key, $ttl, $serialized);
// Теги зберігаються як Redis Sets
foreach ($tags as $tag) {
$this->redis->sAdd("tag:{$tag}", $key);
$this->redis->expire("tag:{$tag}", $ttl + 3600);
}
}
public function invalidateTag(string $tag): void
{
$keys = $this->redis->sMembers("tag:{$tag}");
if ($keys) {
$this->redis->del(...$keys);
}
$this->redis->del("tag:{$tag}");
}
}
Теги в Redis реалізовані через Sets. Інвалідація за тегом — атомарна операція без блокувань файлової системи.
Стратегії кешування
Модуль підтримує кілька стратегій для різних типів даних:
- TTL-кеш — класичний кеш із часом життя. Для даних, що рідко змінюються: налаштування сайту, список регіонів, параметри доставки
-
Event-invalidation — кеш скидається при події Бітрікс. Підвішується на
OnAfterIBlockElementAdd,OnAfterIBlockElementUpdateтощо - Stale-while-revalidate — застарілий кеш повертається негайно, а у фоні запускається перегенерація через агент. Усуває «натовп» при промаху кешу
- Request-scoped — кеш на час одного HTTP-запиту (in-memory array). Уникає повторних запитів до БД в межах одного запиту
Прогрів кешу
При скиданні кешу перший запит завжди повільний — іде до БД. При високому навантаженні це призводить до spike. Агент прогріву вирішує проблему:
// Зареєстровані warmup-задачі
$cache->registerWarmup('catalog_menu', function() {
return CIBlockElement::GetList(/* повний каталог */);
}, ['iblock_main_catalog'], 7200);
// Агент запускається раз на годину й оновлює кеш до закінчення TTL
\Vendor\Cache\WarmupAgent::run();
Моніторинг та статистика
Таблиця b_vendor_cache_stat — для агрегованої статистики за ключами:
-
key_prefix,hits,misses,avg_ttl,last_hit_at
В адміністративному інтерфейсі:
- Hit rate за категоріями ключів
- Топ «холодних» ключів (багато промахів)
- Розмір кешу за бекендами
- Ручна інвалідація за тегом або ключем
- Лог останніх операцій інвалідації
Інтеграція з компонентами Бітрікс
Стандартні компоненти використовують $APPLICATION->IncludeComponent() з параметром CACHE_TYPE. Модуль перехоплює цей механізм і перенаправляє до Redis:
// В init.php після підключення модуля
\Vendor\Cache\BitrixCacheBridge::install();
// → Перевизначає \Bitrix\Main\Data\Cache::createInstance()
// повертаючи Redis-бекенд замість файлового
Bridge робить заміну прозорою — компоненти продовжують працювати без змін коду.
Терміни розробки
| Етап | Термін |
|---|---|
| Архітектура CacheManager, інтерфейс бекенду | 1 день |
| Redis-бекенд із підтримкою тегів | 2 дні |
| Стратегії: stale-while-revalidate, request-scoped | 2 дні |
| Агент прогріву кешу | 1 день |
| Bridge для стандартних компонентів Бітрікс | 1 день |
| Статистика, адміністративний інтерфейс | 2 дні |
| Тестування під навантаженням | 1 день |
Разом: 10 робочих днів. Для проєктів із кластером PHP-серверів — додаткове налаштування Redis Cluster або Sentinel: +1–2 дні.







