Цель статьи — показать, как спроектировать и запустить сайт или магазин с сотнями тысяч и миллионами записей.
1. Когда нужен «большой» стек
Признаки:
- Каталог от 100k до 5M товаров или записей
- Фасетные фильтры и быстрый поиск
- Пики трафика (распродажи, инфоповоды)
- Много интеграций (ERP, CRM, BI, маркетплейсы)
Цели по метрикам (ориентиры):
- p95 поискового запроса ≤ 200 мс
- p95 PLP (страница списка) ≤ 300 мс
- Лаг индексации после изменения цены/стока < 5 минут
2. Базовые принципы архитектуры
- Разделение чтения и записи
- Запись: админка, импорт, вебхуки
- Чтение: витрина, поиск, каталог, публичные API
- Headless‑подход
- Витрина: Next.js/Nuxt с SSG/ISR
- WordPress: CMS и REST API
- Внешний поиск и фасетки
- Elasticsearch или Manticore (self‑hosted), Algolia (SaaS)
- Асинхронная обработка
- Очереди для импорта, переиндексации, писем, интеграций
- Кэширование на всех слоях
- Redis object cache, CDN/edge‑cache, microcache на веб‑сервере
Схема запросов: Браузер → CDN/Edge → Фронт → API → БД/Кэш → Поисковый индекс → Очереди.
3. Хранилище и база данных
- MySQL/MariaDB (InnoDB), отдельные диски под данные и журналы, NVMe
- Минимально необходимые индексы. Не индексируйте всё подряд
- Реплика БД для чтения. Основной узел — для записи
- WooCommerce: включить HPOS (High‑Performance Order Storage)
- Массовые изменения — пакетами и в окно обслуживания
Настройки по умолчанию (ориентиры):
- innodb_buffer_pool_size ≈ 50–70% RAM
- Медленные запросы включены, алерты по p95
- Мониторинг лага репликации
4. Импорт и поток данных
Инструменты: WP‑CLI, Action Scheduler, WP All Import, собственные воркеры.
Очереди: Redis Streams, RabbitMQ или SQS. Обязательно ретраи и DLQ.
Процесс:
- Получение источника (CSV/JSON/вебхук)
- Разбиение на чанки по 1–5k записей
- Постановка задач в очередь
- Воркеры записывают в БД (идемпотентно: внешний_id → post_id)
- Событие на переиндексацию
- Контрольные метрики и отчёт по ошибкам
Пример команд:
# Поставить импорт в очередь
wp bigdata:enqueue-import --file=products.csv --chunk=2000
# Запустить воркеры
wp bigdata:worker run --concurrency=4
Псевдокод воркера:
function handle_chunk(array $rows) {
foreach ($rows as $row) {
$pid = upsert_product($row); // идемпотентно
dispatch_to_indexer($pid); // обновить индекс
}
}
5. Поиск и фасеты
Зачем выносить поиск:
- LIKE и сложные JOIN по postmeta плохо масштабируются
- Внешний индекс даёт быстрые агрегаты, сортировки и курсорную пагинацию
Подходы:
- Elasticsearch: агрегаты, сортировки, горизонтальное масштабирование
- Manticore: лёгкий self‑hosted, хорошая морфология для RU, RT‑индексы
- Algolia: SaaS, простой старт, оплата за запросы
Минимальная схема документа:
{
"id": 123,
"slug": "nike-air-max-270",
"title": "Nike Air Max 270",
"brand": "Nike",
"price": 129.90,
"currency": "USD",
"availability": "in_stock",
"rating": 4.6,
"attributes": {"color": ["black", "white"], "size": ["40", "41"]},
"popularity": 0.87,
"updated_at": "2025-10-05T12:01:00Z"
}
Рекомендации:
- Храните предрассчитанные поля для сортировок и фасеток
- Для глубокой пагинации используйте cursor/search_after
- Обновляйте индекс триггерами на сохранение и ночными батчами
6. Витрина (PLP/PDP)
- PLP получает результаты и агрегаты из поискового индекса
- Пагинация без OFFSET. Используйте курсоры
- Edge‑кэш популярных фильтров. Инвалидация по тегам
- PDP может быть гибридной (часть данных из БД, часть — из индекса)
7. API‑слой
- WordPress REST API и WooCommerce REST
- Отдавайте только нужные поля, используйте ETag/If‑None‑Match
- Кастомные эндпоинты для пакетных операций
- Альтернатива: WPGraphQL, кэширование резолверов
- Защита: rate‑limiting, подписи запросов, WAF
Пример кастомного эндпоинта:
add_action('rest_api_init', function () {
register_rest_route('bigdata/v1', '/products/bulk', [
'methods' => 'GET',
'callback' => 'get_bulk_products',
'args' => ['page' => ['default' => 1]],
]);
});
function get_bulk_products($request) {
$args = ['post_type' => 'product', 'posts_per_page' => 1000, 'paged' => $request['page']];
return rest_ensure_response(get_posts($args));
}
8. Производительность и наблюдаемость
Кэш:
- Redis object cache
- CDN/edge cache
- Microcache на Nginx/LiteSpeed
Нагрузочное тестирование:
- k6, Locust или JMeter
- Профили: поиск с фасетками, распродажа, массовые импорты
Наблюдаемость:
- Метрики: p50/p95/p99 по ключевым маршрутам, error rate, лаги очередей и репликации
- Трейсинг: OpenTelemetry + бэкенд (Jaeger/Tempo)
- Логи: медленные запросы MySQL, ошибки PHP, воркеры
9. Безопасность и бэкапы
- Инкрементные бэкапы БД и файлов
- Проверка восстановления по расписанию
- Хранение секретов в Vault/Parameter Store
- Ограничение и аудит доступа к админке и API
10. Типовые проблемы и решения
- Медленный поиск на MySQL Решение: внешний индекс, пред‑агрегации
- Частые инвалидации кэша Решение: теговая инвалидация, иерархическое ключевание, разные TTL
- Рост wp_postmeta Решение: вывод фасеток в индекс, очистка неиспользуемых мета, HPOS
- Долгие массовые UPDATE Решение: батчи, очереди, окна обслуживания, миграции с откатами
11. Контрольные списки
База данных:
- [ ] innodb_buffer_pool_size настроен
- [ ] Реплика для чтения
- [ ] Медленные запросы и алерты включены
Поиск:
- [ ] Индекс содержит поля для сортировок и фасеток
- [ ] Инкрементальные обновления и ночные батчи
- [ ] Пагинация курсором/search_after
Витрина:
- [ ] Edge‑кэш и теговая инвалидация
- [ ] PLP без OFFSET
- [ ] Критические ресурсы прелоадятся
Импорт:
- [ ] Очереди, ретраи, DLQ
- [ ] Идемпотентность (внешний_id → post_id)
- [ ] Мониторинг ошибок и отчёты
Наблюдаемость:
- [ ] Дашборды p95 PLP/поиск
- [ ] Лаг репликации и лаг индексации
- [ ] Алерты на рост 5xx и рост очередей
12. Пошаговая миграция к «большой» архитектуре
- Подключить Redis object cache и CDN
- Включить HPOS (WooCommerce)
- Внедрить внешний поиск на часть маршрутов (canary)
- Перевести импорт на очереди и батчи
- Вынести PLP в headless‑витрину, PDP оставить гибридно
- Добавить метрики, трассировку, алерты
- Прогнать нагрузочные сценарии и скорректировать лимиты
13. Итог
Ключевые опоры «большого» проекта на WordPress/WooCommerce:
- База данных хранит факты. Поиск и фасеты — во внешнем индексе
- Запись и интеграции — асинхронно через очереди
- Чтение — через кэш и CDN
- Производительность и стабильность — через метрики, трассировку и алерты
Такой подход масштабируется до миллионов единиц контента и выдерживает пики нагрузки с предсказуемыми SLA.