MAATRIX / Блог / Сколько RAM нужно для Meilisearch

Сколько RAM нужно для Meilisearch

MAATRIX

Meilisearch выбирают, когда Elasticsearch кажется избыточным: поднять его проще, память он ест бережнее, а из коробки есть опечатко-устойчивый полнотекстовый поиск с ранжированием по релевантности. Но «бережнее» не значит «сколько угодно на любом VPS» — если недооценить RAM, индексация упадёт по OOM в самый неподходящий момент, обычно ночью на проде. Разберём, откуда берётся аппетит к памяти у Meilisearch и как посчитать нужный объём под конкретный датасет, а не гадать по чужим отзывам.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Как Meilisearch хранит данные и почему это важно для RAM

Meilisearch написан на Rust и под капотом использует LMDB (Lightning Memory-Mapped Database) — движок хранения, который проецирует файлы индекса прямо в адресное пространство процесса через mmap. Это ключевой момент: сами данные лежат на диске, но операционная система активно кеширует страницы файла в RAM, и чем больше «горячих» страниц помещается в память, тем быстрее поиск. Формально Meilisearch может работать и с индексом, который не помещается в RAM целиком — ОС будет подкачивать страницы с диска, — но тогда каждый промах кеша это дисковый I/O, и на медленном диске (особенно на сетевых томах) поиск ощутимо проседает.

Отсюда практический вывод: RAM для Meilisearch — это не жёсткий лимит, без которого процесс не стартует, а ресурс, который прямо определяет скорость. Мало памяти — работать будет, но медленно и с риском OOM в моменты пиковой нагрузки. Именно поэтому вопрос «сколько нужно» правильнее ставить не как «минимум для запуска», а как «сколько для стабильной работы с вашим объёмом данных».

Второй момент — это RSS самого процесса meilisearch, не связанный напрямую с mmap-страницами: буферы во время обработки запросов, кеш facet-фильтров, промежуточные структуры при построении ранжирования. На небольших индексах (до нескольких сотен мегабайт) этот оверхед может быть заметнее, чем сам объём данных.

Индексация — самый прожорливый момент по памяти

Основной пик потребления RAM у Meilisearch приходится не на обслуживание поисковых запросов, а на индексацию — построение обратных индексов, префиксных деревьев для опечатко-устойчивости и структур для сортировки и фильтрации. По архитектуре движка (документация Meilisearch прямо об этом предупреждает) во время индексации в памяти одновременно держатся промежуточные структуры для нескольких типов индексов сразу, поэтому пиковое потребление в моменте индексации может в несколько раз превышать финальный размер индекса на диске. Точный коэффициент зависит от количества searchableAttributes, filterableAttributes, sortableAttributes и языка контента (токенизация кириллицы и CJK тяжелее латиницы) — универсальной цифры тут нет, и любой, кто называет вам точный процент без знания вашей схемы, скорее всего гадает так же, как и вы.

Что можно утверждать уверенно:

  • Пик по RAM — во время POST /indexes/{index}/documents при первой полной загрузке или при массовом обновлении, а не во время обычных GET /search.
  • Индексация мелкими батчами (по 1000-5000 документов) вместо одного гигантского файла снижает пиковое потребление, хотя и немного увеличивает общее время.
  • После завершения индексации RSS процесса обычно снижается — Meilisearch освобождает промежуточные буферы, реальный «рабочий» объём памяти в режиме обслуживания запросов заметно ниже пикового.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Формула расчёта RAM под свой датасет

Раз точных коэффициентов из документации не вывести, используйте инженерный подход «с запасом», а не точную формулу:

  1. Посчитайте суммарный объём индексируемых полей в JSON — не всей базы данных, а только тех полей, что реально идут в Meilisearch (searchableAttributes + метаданные для фильтров). Часто это в разы меньше, чем полная запись в вашей основной БД.
  2. Заложите на финальный индекс на диске объём, сопоставимый с исходным JSON-датасетом (обратные индексы и префиксные структуры добавляют накладные расходы, но LMDB также сжимает данные постранично).
  3. Под RAM для обслуживания запросов — ориентируйтесь на объём финального индекса, чтобы горячие данные помещались в файловый кеш ОС целиком.
  4. Под RAM на индексацию — добавьте запас в 1.5-2 раза сверх пункта 3 на время индексации; это ориентир, а не гарантированное число, и его стоит проверить на своих данных перед продакшеном.
  5. Прибавьте фиксированный оверхед на ОС, systemd, логи, обвязку (nginx/certbot, если поиск за реверс-прокси) — на VPS это обычно 300-500 МБ.

Если сомневаетесь — тестируйте на копии прод-датасета на сервере с мониторингом (free -h, docker stats или htop) во время полной переиндексации, а не запускайте оценку вслепую на боевом трафике.

Примеры: сколько нужно для типичных задач

Ниже — ориентировочные сценарии для оценки порядка величины, а не точные цифры для копирования в тикет:

СценарийОбъём индексируемых данныхRAM для обслуживанияRAM с запасом на индексацию
Поиск по каталогу интернет-магазина, 5-10 тыс. товаровдо 50 МБ JSON1 ГБ2 ГБ
Поиск по статьям блога/базе знаний, 10-50 тыс. документов100-300 МБ JSON2 ГБ4 ГБ
Поиск по логам поддержки, тикетам, большому каталогу B2B1-3 ГБ JSON4-6 ГБ8 ГБ
Крупный маркетплейс, сотни тысяч SKU с фильтрамиот 5 ГБ JSON8+ ГБ16 ГБ и выше

Для первых двух строк вполне хватает бюджетного VPS — это как раз тот случай, когда 2-4 ГБ RAM закрывают задачу с запасом, и не нужно сразу брать выделенный сервер. Если не уверены, сколько памяти закладывать «про запас» на будущий рост данных, у нас есть отдельный разбор того, сколько оперативной памяти закладывать с запасом — логика та же: считать не от текущего объёма, а от прогноза на 6-12 месяцев.

Настройка лимитов памяти в конфиге

Meilisearch умеет ограничивать себя явно, вместо того чтобы полагаться на OOM killer ядра. Ключевая переменная — MEILI_MAX_INDEXING_MEMORY, она задаёт потолок памяти именно на процесс индексации:

# docker-compose.yml
services:
  meilisearch:
    image: getmeili/meilisearch:v1.10
    restart: unless-stopped
    environment:
      MEILI_ENV: production
      MEILI_MASTER_KEY: ${MEILI_MASTER_KEY}
      MEILI_MAX_INDEXING_MEMORY: 1500Mb
      MEILI_MAX_INDEXING_THREADS: 2
      MEILI_HTTP_ADDR: 0.0.0.0:7700
    ports:
      - "127.0.0.1:7700:7700"
    volumes:
      - meili_data:/meili_data
    deploy:
      resources:
        limits:
          memory: 2g

volumes:
  meili_data:

Здесь стоит понимать разницу между MEILI_MAX_INDEXING_MEMORY (мягкий лимит внутри самого Meilisearch — при приближении к порогу он начинает сбрасывать промежуточные данные на диск раньше, что снижает пик RSS, но замедляет индексацию) и deploy.resources.limits.memory в Docker (жёсткий cgroup-лимит: превысил — контейнер убит OOM killer без вопросов). Разумная практика — выставить внутренний лимит Meilisearch заметно ниже, чем лимит контейнера, чтобы у процесса был буфер на служебные накладные расходы:

# Пример: на сервере с 4 ГБ RAM
MEILI_MAX_INDEXING_MEMORY: 2500Mb    # мягкий лимит для Meilisearch
# лимит контейнера — 3.5g, ОС и системным службам оставляем 0.5g

Meilisearch за реверс-прокси стоит прятать за nginx с базовой авторизацией или сетевыми правилами, а не открывать порт 7700 наружу напрямую — мастер-ключ через заголовок Authorization не заменяет сетевую изоляцию. Если ещё не настраивали проксирование, у нас есть инструкция по настройке nginx как реверс-прокси.

Как понять, что памяти не хватает, и что делать

Признаки нехватки RAM для Meilisearch обычно однозначны:

# Проверить текущее потребление процесса
docker stats meilisearch --no-stream

# Общая картина по серверу
free -h

# Есть ли активный OOM kill в логах ядра
dmesg -T | grep -i "killed process"
journalctl -k | grep -i "out of memory"

Если видите в dmesg строку вида Out of memory: Killed process ... (meilisearch) — это не «баг Meilisearch», это честный сигнал: заложенной памяти не хватило на пик индексации. Варианты решения по порядку приоритета:

  • Индексировать батчами меньшего размера — снижает пиковое потребление ценой времени, самое дешёвое решение.
  • Снизить MEILI_MAX_INDEXING_MEMORY — заставит Meilisearch чаще сбрасывать промежуточные данные на диск; индексация замедлится, но упадёт риск OOM.
  • Добавить swap — не решает проблему производительности (LMDB и так работает через mmap, а своп поверх этого добавляет ещё один слой подкачки), но может спасти от жёсткого падения процесса на разовой тяжёлой индексации. Разумный размер свопа для такого сценария разобран в статье про правильный размер swap для VPS.
  • Увеличить RAM сервера — если нехватка систематическая, а не разовый всплеск, это единственное решение, которое не требует компромиссов по скорости.

Отдельно проверяйте endpoint статистики самого Meilisearch — он показывает размер индексов на диске, что помогает пересчитать формулу из предыдущего раздела на реальных, а не гипотетических цифрах:

curl -s http://127.0.0.1:7700/indexes/products/stats \
  -H "Authorization: Bearer $MEILI_MASTER_KEY" | jq

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Хватит ли 1 ГБ RAM для теста Meilisearch?

Для знакомства с движком на игрушечном датасете (пара тысяч документов) — да, запустится и будет работать. Для реальной индексации даже небольшого прод-каталога закладывайте от 2 ГБ, иначе первая же полная переиндексация рискует упасть по памяти.

Meilisearch ест меньше RAM, чем Elasticsearch?

В большинстве сравнимых сценариев — да, за счёт более компактного индекса и отсутствия JVM с её собственным оверхедом на кучу. Но это не значит «памяти вообще не нужно» — на больших датасетах разница в абсолютных цифрах не так драматична, как в маркетинговых материалах.

Можно ли ограничить RAM без риска, что Meilisearch просто откажется индексировать?

Да, MEILI_MAX_INDEXING_MEMORY — это мягкий лимит, движок адаптируется, сбрасывая данные на диск чаще, а не падает при достижении порога. Падает он при превышении лимита самой ОС/контейнера, а не собственного мягкого лимита.

Нужен ли SSD/NVMe, если данные всё равно в RAM через mmap?

Да, обязательно — до тех пор, пока весь индекс не осел в файловом кеше ОС (после старта сервиса или на холодных данных), запросы идут через дисковый I/O. На HDD или медленной сетевой ФС просадки будут заметны даже с достаточным объёмом RAM.

Как расти по памяти вместе с ростом каталога?

Пересчитывайте по формуле выше при каждом заметном росте датасета (условно — при удвоении числа документов) и мониторьте RSS процесса через docker stats в моменты плановой переиндексации, а не только «на глаз» по субъективному ощущению скорости поиска.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →