Кеш в Drupal: как устроены bins, теги и контексты
В Drupal кеш — это не одна таблица и не один переключатель. Разбираем, как связаны cache bins, render cache, cache tags и cache contexts, почему данные становятся устаревшими и что измерять под нагрузкой.

В Drupal 10.x и 11.x кеш может ускорить страницу, но одновременно добавить несколько причин для сложного сбоя: один объект живёт в своём cache bin, HTML зависит от контекстов, а изменение сущности инвалидирует данные через cache tags. Поэтому очистка всей базы кеша часто лечит симптом, но скрывает ошибку в зависимости между данными и результатом.
Кеш в Drupal — это несколько независимых механизмов
Drupal не складывает все кешированные значения в один общий слой. Каждый тип данных обращается к своему cache bin1. Bin выбирает backend, хранит значения и отвечает за операции чтения, записи и удаления. В стандартной конфигурации backend обычно использует базу данных, но отдельные bins можно направить в Redis или другой поддерживаемый слой.
Поверх bins работают более высокие механизмы:
- Cache API хранит произвольные результаты: запросы, вычисления, ответы внешних сервисов.
- Render cache сохраняет результат сборки render array и учитывает его зависимости.
- Dynamic Page Cache кеширует собранные страницы с учётом контекста запроса, в том числе для персонализированного вывода.
- Internal Page Cache хранит готовые ответы для анонимных посетителей.
Эти уровни не заменяют друг друга. Если страница повторно собирается из кешированных фрагментов, очистка page cache не обязательно удалит записи render cache. И наоборот: сброс render cache не гарантирует, что браузер или внешний CDN немедленно перестанет отдавать старый HTTP-ответ.
В Drupal кешируется не только значение, но и набор условий, при которых это значение допустимо показывать.
Что происходит при записи значения
Вызов Cache API обычно работает с четырьмя сущностями: bin, ключом, данными и метаданными кешируемости. Ключ должен однозначно описывать результат. Метаданные задают срок жизни и зависимости от данных сайта.
В database backend записи физически находятся в таблицах с именами вроде cache_default и cache_render. Суффикс соответствует bin. Точная структура таблиц зависит от версии Drupal и используемого backend, поэтому обращаться к ним прямым SQL из прикладного кода не стоит.
У записи есть как минимум такие логические свойства:
- идентификатор — ключ, по которому Drupal ищет результат;
- данные — сериализованное значение;
- время истечения — момент, после которого запись нельзя считать свежей;
- cache tags — связи с объектами и наборами данных;
- cache contexts — условия, при которых результат отличается;
- checksum — служебный признак для проверки набора тегов в поддерживаемых сценариях.
Истечение времени не означает немедленное физическое удаление строки. Backend может удалить просроченную запись при следующем обращении или во время очистки. Это важное различие: размер таблицы не показывает, сколько записей реально участвует в выдаче.
Cache bins разделяют ответственность
Bin нужен не только для удобства именования. Разные данные имеют разный жизненный цикл и требования к производительности. Кеш маршрутов, конфигурации и отрендеренного HTML нельзя рассматривать как один поток: очистка одного bin не должна автоматически уничтожать остальные.
| Слой | Что хранит | Когда проверять | Риск ошибки |
|---|---|---|---|
| Cache API | Результаты вычислений и запросов | При повторном вызове дорогой операции | В ключ не попал параметр запроса |
| Render cache | Собранные render arrays и фрагменты | При построении вывода блока или сущности | Фрагмент показан не тому пользователю |
| Dynamic Page Cache | Ответы страниц с вариациями | До полной сборки страницы | Не учтён cache context |
| Internal Page Cache | Готовые ответы для анонимных запросов | До запуска большей части Drupal | Старый HTML продолжает отдаваться гостям |
Три измерения кешируемости render array
Render API описывает кешируемость не одним числом. Для каждого render array важны max-age, cache tags и cache contexts. Drupal собирает эти метаданные по дереву: родительский результат получает зависимости дочерних элементов.
Max-age отвечает за время
max-age задаёт максимальный срок, в течение которого результат считается свежим. Значение не равно гарантии, что пользователь увидит его ровно столько: внешний кеш, браузер и CDN могут иметь собственные правила. Нулевой срок означает, что результат нельзя считать кешируемым на время, но сам render array всё ещё может участвовать в общей сборке.
Cache tags отвечают за данные
Тег связывает результат с изменяемой сущностью или другим источником данных. Когда материал, меню или конфигурация меняются, Drupal инвалидирует соответствующие теги. Это точнее, чем удалять весь кеш: записи, не связанные с изменённым объектом, остаются пригодными.
Проблема появляется, когда модуль читает данные, но не добавляет их теги в кешируемый результат. Страница может иметь длинный срок жизни и продолжать показывать старое значение после обновления записи. Полная очистка кеша временно маскирует дефект, но после следующей записи он возвращается.
Cache contexts отвечают за различия запроса
Контекст описывает фактор, от которого зависит результат: язык, роль пользователя, URL, способ доставки или другой параметр, предусмотренный системой. Drupal включает контекст в вариацию кеша. Поэтому одна страница может иметь несколько вариантов, а не одну запись на URL.
Добавлять контексты «на всякий случай» тоже опасно. Чем больше факторов участвует в ключе, тем больше вариантов создаётся и тем ниже вероятность повторного попадания в кеш. Если блок зависит от роли, нужно указать именно роль, а не отключать кеш целиком.
Сноска. Cacheability metadata — метаданные кешируемости: срок жизни, теги и контексты, по которым Drupal решает, можно ли повторно использовать результат.
Как связаны render cache и page cache
При построении страницы Drupal может сначала получить готовые фрагменты из render cache, а затем сохранить итоговый ответ на уровне Dynamic Page Cache или Internal Page Cache. Получается цепочка: данные → render array → HTML-фрагменты → HTTP-ответ.
На каждом переходе должны сохраняться зависимости. Если блок зависит от текущего пользователя, но его вывод попал в общий кеш страницы без соответствующего контекста, проблема уже не в backend. Drupal получил неполные метаданные и законно переиспользовал результат там, где разработчик этого не ожидал.
Для анонимных пользователей Internal Page Cache может вернуть ответ раньше, чем код контроллера или построитель страницы снова выполнятся. Поэтому отладка только на авторизованном аккаунте часто вводит в заблуждение: автор видит свежие данные, а гость — старый ответ из отдельного слоя.
Что ломается первым
Старый контент после изменения сущности
Сначала проверьте, какой слой отдаёт ответ: браузер, CDN, page cache или render cache. Затем найдите связь между изменённой сущностью и cache tags. Если тег не дошёл до результата, сброс кеша исправит экран только до следующего периода кеширования.
Персональные данные в общем фрагменте
Частая причина — условие в шаблоне или preprocess-коде, которое зависит от пользователя, но не отражено в cache contexts. Нельзя решать такую проблему добавлением случайного параметра в ключ без понимания слоя: page cache и render cache должны видеть одну и ту же зависимость.
Слишком много вариантов
Широкий набор контекстов увеличивает кардинальность кеша2. В результате таблицы и Redis растут, а hit rate снижается. Анализируйте, какие значения действительно меняют HTML, и не добавляйте контекст для параметра, который влияет только на внутренний запрос.
Ожидание мгновенной очистки
Инвалидация cache tag удаляет пригодность записи для повторного использования, но не обязательно стирает все копии за пределами Drupal. Отдельно проверяйте CDN, reverse proxy и браузерные заголовки. При проблемах с авторизованными страницами также учитывайте Dynamic Page Cache.
Сноска. Кардинальность кеша — количество вариантов одного результата, возникающих из-за различий в URL, языке, роли, устройстве или других контекстах.
Как измерять кеш, а не угадывать
Drupal не даёт универсального числа «ускорения от кеша», которое можно перенести на любой сайт. Результат зависит от версии PHP, базы данных, backend, размера render tree, количества модулей и внешнего прокси. Поэтому сравнивать нужно конкретную конфигурацию.
- Зафиксируйте версию Drupal, PHP, backend кеша, размер базы и тип страницы.
- Снимите время ответа и долю попаданий в кеш для анонимного и авторизованного запроса.
- Повторите тест после очистки relevant bins, а затем после прогрева — иначе сравните холодный и тёплый кеш.
- Проверьте несколько вариантов языка, роли и URL, если они участвуют в контекстах.
- Отдельно измерьте время построения страницы, запросы к базе и передачу ответа через CDN или reverse proxy.
Минимальный набор наблюдений — latency на одинаковом маршруте, число SQL-запросов, размер ответа, hit/miss по внешнему кешу и рост таблиц cache_*. Для продакшена добавьте частоту инвалидирования и время прогрева после деплоя.
Что делать дальше
Начните с карты зависимостей одной проблемной страницы: какие блоки зависят от пользователя, языка и сущностей, какой page cache её обслуживает и какие теги должны инвалидироваться. Затем сравните холодный и тёплый запрос, не очищая весь кеш после каждой проверки. После этого настройте мониторинг размера cache bins, времени ответа и доли попаданий на анонимных и авторизованных маршрутах.
Подробные правила описаны в официальной документации Drupal по Cache API и кешируемости render arrays. Инвалидация кеша — отдельная тема; здесь важно сначала правильно описать зависимости результата.
Создатель презентаций: Структура и текст каждого слайда: заголовки-утверждения, одна мысль на слайд, заметки докладчику.
Спросить за 150 ₽Источники: Drupal Cache API, Cacheability of render arrays
Частые вопросы
Чем cache tags отличаются от cache contexts?
Почему очистка всего кеша помогает, но проблема возвращается?
Почему автор видит свежие данные, а гость — старые?
Можно ли отключить весь кеш Drupal на время отладки?
Что делать, если таблицы cache_* быстро растут?
Нужно ли добавлять cache context для каждого параметра пользователя?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.