Лучшие практики эффективного шардинга и масштабирования кластеров MongoDB

Выбирайте лучшие ключи шардирования MongoDB, отслеживайте балансировку и проектируйте запросы, избегающие ненужной работы scatter-gather.

Лучшие практики эффективного шардирования и масштабирования кластеров MongoDB

Шардирование MongoDB распределяет коллекцию по нескольким шардам, чтобы один набор реплик не должен был нести все ваши данные или трафик. Это может решить реальные проблемы масштабирования, но плохой ключ шардирования может создать горячие шарды, медленные scatter-gather запросы и операционную работу, которую трудно отменить.

Используйте шардирование, когда один набор реплик больше не может справиться с объемом данных, пропускной способностью записи или нагрузкой чтения после того, как вы уже решили основы: индексы, проектирование схемы, выбор оборудования и настройка запросов.


Понимание основных компонентов шардированного кластера

Функциональный шардированный кластер полагается на несколько взаимосвязанных компонентов, работающих в тандеме:

  1. Шарды (наборы реплик шардов): Каждый шард обычно представляет собой набор реплик, который содержит подмножество всего набора данных. Данные разделяются между этими шардами.
  2. Маршрутизаторы запросов (процессы Mongos): Эти процессы получают клиентские запросы, определяют, какой шард содержит требуемые данные (на основе метаданных), маршрутизируют запрос, агрегируют результаты и возвращают их клиенту. Они не имеют состояния и легко масштабируются.
  3. Серверы конфигурации (Config Servers): Эти выделенные наборы реплик хранят метаданные (карту кластера), которые сообщают процессам mongos, где находятся конкретные фрагменты данных. Они критически важны для работы кластера и должны быть высокодоступными.

Ключевая стратегия 1: Выбор оптимального ключа шардирования

Ключ шардирования — это самое важное решение при шардировании. Он определяет, как данные распределяются по вашим шардам. Хорошо выбранный ключ шардирования приводит к равномерному распределению данных и эффективной маршрутизации запросов; плохой ключ приводит к горячим точкам и несбалансированным кластерам.

Характеристики эффективного ключа шардирования

Идеальный ключ шардирования должен обладать тремя основными характеристиками:

  1. Высокая кардинальность: Ключ должен иметь много уникальных значений, чтобы обеспечить детальное разделение. Низкая кардинальность приводит к меньшему количеству фрагментов в целом.
  2. Высокая частота записи/равномерное распределение: Записи должны равномерно распределяться по всем значениям ключа шардирования, чтобы предотвратить перегрузку одного шарда (горячая точка).
  3. Шаблоны запросов: Запросы должны по возможности нацеливаться на ключ шардирования, чтобы обеспечить целевые запросы (маршрутизацию к конкретным шардам). Запросы, требующие сканирования всех шардов (scatter-gather запросы), значительно медленнее.

Методы шардирования и их последствия

MongoDB поддерживает два основных метода шардирования:

  • Хешированное шардирование: Использует хеш-функцию для значения ключа шардирования. Это обеспечивает отличное распределение данных, даже для последовательных ключей, распределяя записи по всем доступным шардам. Лучше всего подходит для высокой пропускной способности записи, когда локальность запросов менее важна.
  • Диапазонное шардирование: Разделяет данные на основе диапазонов ключа шардирования (например, все пользователи с ID 1-1000 попадают на шард A). Лучше всего, когда шаблоны запросов соответствуют поиску по диапазону (например, запросы по диапазону дат или алфавитному диапазону ID).

⚠️ Предупреждение о диапазонном шардировании: Если ваш шаблон вставки данных следует строго возрастающей последовательности (например, временные метки или автоинкрементные ID), диапазонное шардирование приведет к тому, что все записи попадут в самый новый фрагмент, что приведет к значительной горячей точке на последнем шарде.

Пример: Применение хешированного шардирования

Если вы выбираете поле, такое как userId, и ваши запросы часто фильтруют по нему, хеширование равномерно распределяет записи:

// Выберите базу данных и коллекцию
use myAppDB

// Хешируйте поле userId для шардирования
sh.shardCollection("myAppDB.users", { "userId": "hashed" })

Ключевая стратегия 2: Управление распределением данных и балансировкой

Даже с идеальным ключом шардирования фрагменты данных (физические единицы данных, хранящиеся на шардах) могут стать неравномерными по размеру или распределению из-за изменяющихся шаблонов запросов или начального дисбаланса нагрузки. Процесс Балансировщика обрабатывает миграцию этих фрагментов.

Мониторинг балансировщика

Крайне важно отслеживать метрики баланса кластера. Несбалансированные фрагменты приводят к недоиспользованию ресурсов на одних шардах, в то время как другие перегружаются.

Используйте команду sh.status() в оболочке, чтобы просмотреть общий статус, включая то, какие фрагменты мигрируют.

Управление балансировщиком

Хотя балансировщик работает автоматически, вы можете временно отключить его во время окон высокого обслуживания или больших пакетных импортов, чтобы контролировать потребление ресурсов:

// Проверьте текущий статус
sh.getBalancerState()

// Временно отключите балансировку
sh.stopBalancer()

// ... Выполните обслуживание или большой импорт ...

// Перезапустите балансировку после завершения
sh.startBalancer()

Лучшая практика: Никогда не отключайте балансировщик навсегда. Если вы его отключите, планируйте регулярные проверки, чтобы убедиться, что данные остаются равномерно распределенными по мере роста приложения.

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

Фрагменты не должны быть слишком маленькими, так как это создает избыточные накладные расходы на метаданные и замедляет балансировщик. И наоборот, слишком большие фрагменты приводят к медленной миграции и плохим возможностям балансировки нагрузки.

  • Размер фрагмента по умолчанию: Размер фрагмента по умолчанию в MongoDB обычно подходит для многих кластеров. Проверьте документацию вашей версии MongoDB перед его изменением.
  • Настройка размера фрагмента: Изменяйте размер фрагмента только тогда, когда у вас есть четкая операционная причина, например, миграция занимает слишком много времени или накладные расходы на метаданные становятся чрезмерными. Поддерживаемый метод менялся в разных версиях MongoDB, поэтому проверьте текущую команду для вашей версии перед применением.

Ключевая стратегия 3: Оптимизация производительности чтения и записи

Шардирование изменяет маршрутизацию чтения и записи, что требует специфической настройки производительности.

Целевые запросы против Scatter-Gather запросов

  • Целевые запросы: Запросы, которые включают ключ шардирования (или префикс ключа шардирования при использовании диапазонного шардирования), позволяют маршрутизатору mongos отправлять запрос напрямую к одному или нескольким шардам. Они быстрые.
  • Scatter-Gather запросы: Запросы, которые не используют ключ шардирования, должны быть отправлены на каждый шард, что увеличивает задержку сети и накладные расходы на обработку.

Практический совет: Проектируйте запросы приложения так, чтобы они использовали ключ шардирования, когда это возможно. Для запросов, которые должны сканировать широко, рассмотрите использование предпочтений чтения, которые отдают предпочтение вторичным членам наборов реплик, чтобы изолировать нагрузку от основных членов.

Предпочтение чтения в шардированных кластерах

Шардированные кластеры обрабатывают предпочтения чтения на уровне клиента. Убедитесь, что код вашего приложения правильно устанавливает предпочтения чтения в зависимости от критичности операции:

  • primary (По умолчанию): Чтение идет к основному члену набора реплик каждого шарда.
  • nearest: Чтение идет к члену набора реплик, географически или сетево ближайшему к приложению.
  • secondaryPreferred: Чтение отправляется на вторичные члены, если они доступны, что полезно для разгрузки отчетных или аналитических запросов с основных членов.

Избегание ловушек индексирования

Убедитесь, что индексы существуют на полях, часто используемых в фильтрах запросов или операциях сортировки, особенно на ключе шардирования и любых префиксных полях ключа шардирования. Несогласованное индексирование между шардами также может привести к неожиданным scatter-gather запросам, если один шард не может использовать индекс.


Операционные лучшие практики для стабильности

Поддержание стабильного, высокопроизводительного шардированного кластера требует постоянной операционной бдительности.

1. Изменения ключа шардирования

Выбирайте ключ шардирования так, как будто его изменение будет дорогим, потому что так оно и есть. Последние версии MongoDB поддерживают больше уточнений ключа шардирования и некоторые обновления значений ключа шардирования, чем старые версии, но правила зависят от вашей версии, шаблона ключа и требований к транзакциям. Не рассчитывайте на легкое переписывание после начала производственного трафика.

2. Устойчивость серверов конфигурации

Серверы конфигурации — это мозг кластера. Если они становятся недоступными, клиенты не могут определить, где находятся данные, что фактически останавливает операции.

  • Всегда развертывайте серверы конфигурации как набор реплик (минимум три члена).
  • Убедитесь, что серверы конфигурации имеют быстрое хранилище и не обременены рабочей нагрузкой приложения.

3. Планирование емкости

Планируйте рост, отслеживая использование ЦП, памяти, дискового ввода-вывода, рост хранилища, задержку репликации и распределение фрагментов на отдельных членах шарда. Добавляйте емкость до того, как один шард станет узким местом, а не полагайтесь на один фиксированный процент использования.

Вывод

Шардирование в MongoDB — это инструмент масштабирования, а не обходной путь для моделирования данных. Выберите ключ шардирования, который распределяет записи и соответствует вашим наиболее важным запросам, отслеживайте балансировку после запуска и, когда это возможно, делайте запросы приложения целевыми.