mFilter 1.2.0 - улучшенное кеширование и скорость
mFilter 1.2.0 — Новая подсистема, которая заранее вычисляет и кэширует данные фильтров, чтобы страницы каталога открывались мгновенно с первого обращения.
На каталогах свыше 10 000 товаров первая загрузка страницы с фильтрами — это боль. MySQL 8 тяжело переваривает запросы к большим таблицам: получить список товаров категории, посчитать значения фильтров, вычислить фасетные счётчики. На 200 000 товаров первая загрузка занимала до 60 секунд. Повторная — из кэша, быстро. Но каждый раз, когда кэш протухал или сбрасывался — опять ожидание.
Все тяжёлые вычисления выполняются заранее — в фоне, по расписанию, когда никто не ждёт. Результаты сохраняются в базу данных. Когда пользователь открывает страницу каталога — система находит готовый результат за миллисекунды вместо того, чтобы считать с нуля. Управление прогревом — через новую вкладку в админке и рекуррентное задание Scheduler.
При загрузке страницы каталога mFilter выполняет три тяжёлые операции. Теперь все три можно прогревать заранее:
В админке mFilter появилась шестая вкладка — Прогрев кэша. Здесь создаются и управляются конфигурации прогрева.
Конфигурация — это связка: какой сниппет вызывать (msProducts, pdoResources) + на каких страницах каталога. Создать можно двумя способами:
Чекбокс «+ счётчики» включён по умолчанию. С ним прогреваются все три типа кэша. Без него — только baseIds.
Новый таск mfl_warmup регистрируется в Scheduler при установке пакета. По умолчанию — рекуррентный, запускается каждые 50 минут. При стандартном TTL в 1 час кэш обновляется с запасом и никогда не протухает.
Интервал и TTL подбираются под конкретный проект. Для каталога в 200 000 товаров прогрев занимает около 30 минут — соответственно, интервал нужен побольше. Для 5 000 товаров прогрев пролетает за минуту, и дефолтные 50 минут — с большим запасом.
При обновлении товарной базы (импорт цен, остатков, новых позиций) ничего делать не нужно — рекуррентный таск обновит кэш при следующем запуске. Если нужна актуальность прямо сейчас — кнопка «Через Scheduler» в админке.
В сниппет mFilter добавлена проверка: перед вызовом element-сниппета система ищет прогретый кэш baseIds. Ключ кэша — MD5-хеш от параметров, влияющих на выборку (element, depth, where, showZeroPrice и т.д.). Параметры вроде tpl, sortby, showLog — не влияют на набор товаров и в хеш не входят.
Если кэш найден — element-сниппет не вызывается вообще. Экономия от 1 до 30 секунд в зависимости от размера категории. Если кэша нет — сниппет отрабатывает как раньше, а конфигурация для будущего прогрева создаётся автоматически.
Аналогично с формой фильтров. mFilterForm при загрузке вычисляет значения фильтров через getFilters() — этот метод уже имел встроенный кэш, но без прогрева первый вызов был тяжёлым. Теперь warmup заполняет этот кэш заранее.
Тестировалось на боевом каталоге — 200 000 товаров, 100 категорий. До прогрева первая загрузка страницы — 15–60 секунд. После прогрева — доли секунды. Полный прогрев каталога — около 30 минут в фоне через Scheduler.
Проблема
На каталогах свыше 10 000 товаров первая загрузка страницы с фильтрами — это боль. MySQL 8 тяжело переваривает запросы к большим таблицам: получить список товаров категории, посчитать значения фильтров, вычислить фасетные счётчики. На 200 000 товаров первая загрузка занимала до 60 секунд. Повторная — из кэша, быстро. Но каждый раз, когда кэш протухал или сбрасывался — опять ожидание.
Решение
Все тяжёлые вычисления выполняются заранее — в фоне, по расписанию, когда никто не ждёт. Результаты сохраняются в базу данных. Когда пользователь открывает страницу каталога — система находит готовый результат за миллисекунды вместо того, чтобы считать с нуля. Управление прогревом — через новую вкладку в админке и рекуррентное задание Scheduler.
Что кэшируется
При загрузке страницы каталога mFilter выполняет три тяжёлые операции. Теперь все три можно прогревать заранее:
- baseIds — список всех ID товаров в категории. Результат вызова element-сниппета (msProducts, pdoResources) с returnIds. На больших каталогах это самый медленный запрос.
- filter values — какие бренды, цвета, размеры доступны в этой категории. Используется формой фильтров (mFilterForm) для построения чекбоксов, слайдеров, цветовых свотчей.
- suggestions — фасетные счётчики. Сколько товаров для каждого значения каждого фильтра. Те самые цифры в скобках рядом с чекбоксами: «Samsung (142)», «Красный (38)».
Вкладка «Прогрев кэша»
В админке mFilter появилась шестая вкладка — Прогрев кэша. Здесь создаются и управляются конфигурации прогрева.
Конфигурация — это связка: какой сниппет вызывать (msProducts, pdoResources) + на каких страницах каталога. Создать можно двумя способами:
- Вручную — нажать «Добавить конфигурацию», вставить вызов сниппета из шаблона и нажать «Распарсить». Парсер понимает Fenom, MODX-теги и JSON. Параметры заполнятся автоматически. Справа — дерево ресурсов для выбора страниц.
- Автоматически — при первом посещении любой страницы каталога конфигурация создаётся сама. В таблице появится запись с пометкой «Авто».
Чекбокс «+ счётчики» включён по умолчанию. С ним прогреваются все три типа кэша. Без него — только baseIds.
Задание планировщика
Новый таск mfl_warmup регистрируется в Scheduler при установке пакета. По умолчанию — рекуррентный, запускается каждые 50 минут. При стандартном TTL в 1 час кэш обновляется с запасом и никогда не протухает.
Интервал и TTL подбираются под конкретный проект. Для каталога в 200 000 товаров прогрев занимает около 30 минут — соответственно, интервал нужен побольше. Для 5 000 товаров прогрев пролетает за минуту, и дефолтные 50 минут — с большим запасом.
При обновлении товарной базы (импорт цен, остатков, новых позиций) ничего делать не нужно — рекуррентный таск обновит кэш при следующем запуске. Если нужна актуальность прямо сейчас — кнопка «Через Scheduler» в админке.
Как это работает внутри
В сниппет mFilter добавлена проверка: перед вызовом element-сниппета система ищет прогретый кэш baseIds. Ключ кэша — MD5-хеш от параметров, влияющих на выборку (element, depth, where, showZeroPrice и т.д.). Параметры вроде tpl, sortby, showLog — не влияют на набор товаров и в хеш не входят.
Если кэш найден — element-сниппет не вызывается вообще. Экономия от 1 до 30 секунд в зависимости от размера категории. Если кэша нет — сниппет отрабатывает как раньше, а конфигурация для будущего прогрева создаётся автоматически.
Аналогично с формой фильтров. mFilterForm при загрузке вычисляет значения фильтров через getFilters() — этот метод уже имел встроенный кэш, но без прогрева первый вызов был тяжёлым. Теперь warmup заполняет этот кэш заранее.
Результат
Тестировалось на боевом каталоге — 200 000 товаров, 100 категорий. До прогрева первая загрузка страницы — 15–60 секунд. После прогрева — доли секунды. Полный прогрев каталога — около 30 минут в фоне через Scheduler.
Прочие улучшения в 1.2.0
- Кэш suggestions теперь сохраняется при первом вычислении — повторные обращения берут из базы
- Временные метки кэша хранятся в UTC — корректная работа при разных таймзонах cron и web
- TvIndexer индексирует только TV из конфигурации фильтров, а не все TV ресурса
- Удалён устаревший механизм прогрева через HTTP-запросы к страницам
Ссылки
Поблагодарить автора
Отправить деньги
Комментарии: 1
На данный момент кеширование отлажено только для каталогов без примененных фильтров. Такие страницы отрываются достаточно быстро. Обычно это 300-400 ms
А вот как сделать удачное кеширование страниц с примененными фильтрами я пока не знаю. Слишком большой набор вариаций и пересечений. Это называется вариативный взрыв. Хорошая новость в том, что даже с одним примененным фильтром товаров в каталоге остается не так много — и вся эта история загрузится сильно быстрее чем пустой каталог.
А вот как сделать удачное кеширование страниц с примененными фильтрами я пока не знаю. Слишком большой набор вариаций и пересечений. Это называется вариативный взрыв. Хорошая новость в том, что даже с одним примененным фильтром товаров в каталоге остается не так много — и вся эта история загрузится сильно быстрее чем пустой каталог.
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.