ARCHITECTURE

Как устроен поиск под капотом

Индексация дорогая и редкая. Выдача — из готового inverted index. Поэтому на 500 000 SKU ответ остаётся в десятках миллисекунд.

Каталог500 000SKU в индексе
P90 search~20 мсТЗ ≤ 400 мс
Suggest~20–50 мсТЗ ≤ 100 мс
Запас к SLA×20+на демо-контуре
01 · СТЕК

Слои системы

Витрина не ходит в CSV. Hot-path — только FastAPI и Meilisearch.

Edge

Nginx

TLS, маршрутизация UI/API, лимит тела фида до 512 МБ.

API

FastAPI

Auth по ключу, классификатор kids/zoo, оркестрация индексации.

Search

Meilisearch

Inverted index, typo-tolerance, синонимы, фасеты, ранжирование.

Meta

PostgreSQL

Только tenants и feed jobs. Не участвует в выдаче товаров.

02 · HOT PATH

Путь одного поискового запроса

01

Запрос

Витрина шлёт GET /v1/search с X-API-Key. CSV на этом пути не читается.

02

Auth + classify

API находит tenant и за доли мс определяет kids / zoo.

03

Meilisearch

Lookup по inverted index: токены → posting lists → ранжирование → фасеты.

04

Ответ

Hits, facets, image_url, response_time_ms и processing_time_ms.

03 · INDEXING

Почему быстро: дорогая индексация, дешёвая выдача

Импорт фида

  1. POST /v1/feeds/upload пишет файл потоком по 1 МБ.
  2. Background job читает CSV итератором.
  3. Документы уходят в Meili батчами по 2000.
  4. Полная замена индекса: delete_all_documents.
  5. Повтор: POST /v1/feeds/{id}/reindex.

Почему миллисекунды

  • Inverted indexПоиск по токенам, не full-table scan на 500k строк
  • Индекс в RAMПосле прогрева нет парсинга 277 МБ фида
  • Тонкий APIТолько auth, classify и один RPC к движку
  • Фасеты в движкеFilterable attributes без повторного обхода каталога
04 · CAPACITY

На сколько одновременных поисков заточено

Оценка для текущего демо: 1× uvicorn + 1× Meilisearch, 500k SKU, shared VPS. Это ориентир по latency, не финальный load-test отчёт.

Комфортный режим200–500RPS
Краткий пик800–1500RPS
In-flight50–150запросов
P90 latency~20мс
Узкие места демо — один API-worker и один инстанс Meili. При росте масштабируется слой чтения, а не «ускоряется CSV».
05 · SCALING

Как масштабировать

Вертикально

  • uvicorn --workers N по числу CPU
  • Meili на отдельный хост 4–8+ ГБ RAM
  • Отдельный Postgres и connection pool

Горизонтально

  • Реплики API за балансировщиком
  • Meili primary + read-replicas
  • Очередь индексации вместо BackgroundTasks
  • Delta-выгрузки вместо full-replace
100k SKUтысячи RPS / узел
500k SKUсотни–низкие тысячи
1–2M SKUreplicas обязательны
5M+ SKUшардирование
06 · INTEGRATION

Ключевые методы API

POST /v1/feeds/upload

Загрузка фида и автозапуск индексации

GET /v1/feeds/{job_id}

Статус: pending → processing → completed

POST /v1/feeds/{job_id}/reindex

Повторная индексация без нового файла

GET /v1/search

Поиск, фасеты, картинки, latency

GET /v1/suggest

Текстовый и товарный саджест

GET /v1/classify

Направление kids / zoo / unknown

Демо-ключ для Authorize: detmir-demo-key-2026