MongoDB Academy · Урок

План масштабирования: от набора реплик до сегментированного кластера

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

Урок 3 из 413 шагов

«План масштабирования: от набора реплик до сегментированного кластера» — бесплатный урок MongoDB Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения MongoDB Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс MongoDB Academy содержит 4 уроков всего.

Когда необходимо масштабирование?

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

Этап 1: один набор реплик

Стандартная отправная точка для любого развёртывания MongoDB — набор реплик из 3 участников: один первичный узел и два вторичных. Это обеспечивает высокую доступность (автоматическое переключение при сбое первичного узла), сохранность данных (записи реплицируются на несколько участников) и масштабирование чтения (для отчётных нагрузок чтение направляется на вторичные узлы). Для нашего итогового проекта электронной коммерции кластер Atlas M30 из 3 участников без труда обрабатывает миллионы заказов в день. Начните с этого варианта и проведите измерения, прежде чем рассматривать сегментирование.

// Capacity metrics to monitor on a single replica set
// (via Atlas Metrics or db.serverStatus())
const metricsToWatch = [
  'connections.current',         // approaching maxIncomingConnections?
  'opcounters.insert',           // write ops/sec approaching primary limit?
  'mem.resident',                // working set fitting in RAM?
  'wiredTiger.cache.bytesCurrentlyInCache', // cache utilisation
  'replicationLag'               // secondaries keeping up?
]

Этап 2: масштабирование чтения с помощью вторичных узлов

Перед сегментированием масштабируйте чтение, направляя аналитические и отчётные запросы на вторичные узлы с помощью readPreference: 'secondary'. Это снижает нагрузку на первичный узел без усложнения эксплуатации. В Atlas аналитические узлы — это выделенные вторичные узлы (которые никогда не становятся первичными), принимающие тяжёлые задачи агрегации без влияния на производительность первичного узла. Такой подход хорошо работает, пока узким местом не становится сама пропускная способность записи.

// Route heavy analytics to secondary nodes
const { MongoClient } = require('mongodb')

const client = new MongoClient(process.env.ATLAS_URI, {
  readPreference: 'secondary'   // global default for this client
})

// Or per-operation
const result = await db.collection('orders').aggregate(
  [ /* heavy reporting pipeline */ ],
  { readPreference: 'secondary' }  // does not compete with primary writes
)

Этап 3: когда выполнять сегментирование

Выполняйте сегментирование, когда достигаете предела, который нельзя устранить вертикальным масштабированием: пропускная способность записи первичного узла исчерпана даже на самом мощном доступном экземпляре; рабочий набор коллекции (активно используемые данные и индексы) не помещается в RAM кластера даже на самом крупном уровне; или отдельная коллекция слишком велика, чтобы хранить её на диске одного кластера. На практике большинство приложений достигает ограничений RAM раньше ограничений пропускной способности записи — ежемесячно отслеживайте использование кэша WiredTiger и размер рабочего набора.

// Indicator: working set exceeding cache
// db.serverStatus().wiredTiger.cache
const cache = db.serverStatus().wiredTiger.cache
const cacheHitRatio = 1 - (cache['pages read into cache'] / cache['pages requested from the cache'])
console.log('Cache hit ratio:', (cacheHitRatio * 100).toFixed(1) + '%')
// Below 95%: working set is not fitting in cache — time to scale

Выбор коллекции для сегментирования

Сегментируйте только те коллекции, которые создают узкое место. На нашей платформе электронной коммерции коллекция orders будет расти быстрее всего и создавать наибольший объём трафика записи. Коллекция products может быть большой, но преимущественно получает операции чтения, которые можно обслуживать со вторичных узлов. Сегментирование orders при сохранении products без сегментирования (на каждом сегменте как широковещательной коллекции) — распространённый и практичный подход.

// Enable sharding on the database
sh.enableSharding('ecommerce')

// Shard the orders collection
sh.shardCollection('ecommerce.orders', { userId: 'hashed' })

// Verify shard distribution
sh.status()
db.orders.getShardDistribution()

Выбор ключа сегмента для заказов

Ключ сегмента для orders должен равномерно распределять записи между сегментами и поддерживать наиболее распространённые шаблоны запросов. Использование userId в качестве хешированного ключа сегмента равномерно распределяет записи, поскольку идентификаторы пользователей имеют высокую кардинальность и случайны. Недостаток: запросы в рамках одного пользователя распределяются по всем сегментам. Диапазонный ключ сегмента { userId: 1, _id: 1 } хранит заказы одного пользователя на одном сегменте (что ускоряет запросы для конкретного пользователя), но создаёт риск перегрева отдельных сегментов, если несколько пользователей генерируют большую часть активности.

// Option 1: Hashed shard key — uniform write distribution
sh.shardCollection('ecommerce.orders', { userId: 'hashed' })
// Pros: even distribution
// Cons: user order history queries scatter across all shards

// Option 2: Compound ranged shard key — user orders co-located
sh.shardCollection('ecommerce.orders', { userId: 1, _id: 1 })
// Pros: all orders for a user are on one shard — fast history queries
// Cons: may create hot shards if a few users dominate traffic

Зональное сегментирование для соблюдения требований к размещению данных

Если платформа электронной коммерции обслуживает несколько регионов с требованиями к размещению данных (данные EU должны оставаться в Европе), используйте зональное сегментирование, чтобы закреплять документы за определёнными сегментами на основе диапазонов ключа сегмента. Создайте зоны для каждого региона, назначьте сегменты зонам и определите, какие диапазоны ключа сегмента соответствуют каждой зоне. Данные пользователей EU останутся на сегментах в регионе EU, что позволит соблюдать GDPR без поддержки отдельных кластеров.

// Zone sharding for regional data residency
// Assign shards to zones
sh.addShardToZone('shard0001', 'EU')
sh.addShardToZone('shard0002', 'US')
sh.addShardToZone('shard0003', 'APAC')

// Define shard key ranges for each region
// (Assuming userId prefix encodes region: 'EU-', 'US-', 'APAC-')
sh.updateZoneKeyRange('ecommerce.orders',
  { userId: 'EU-' }, { userId: 'EU-zzz' }, 'EU'
)
sh.updateZoneKeyRange('ecommerce.orders',
  { userId: 'US-' }, { userId: 'US-zzz' }, 'US'
)

mongos и сервер конфигурации

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

Целевые запросы и запросы с рассылкой по всем шардам

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

// TARGETED: includes shard key (userId) — goes to one shard only
db.orders.find({ userId: 'user-123', status: 'pending' })

// SCATTER-GATHER: no shard key — hits ALL shards (expensive!)
db.orders.find({ status: 'pending', total: { $gt: 100 } })

// Verify with explain in sharded cluster
db.orders.find({ userId: 'user-123' }).explain('executionStats')
// Look for 'SINGLE_SHARD' vs 'SHARD_MERGE' in the winning plan

Планирование ёмкости и мониторинг

Постройте модель ёмкости: умножьте предполагаемый ежедневный прирост документов на средний размер документа, чтобы спрогнозировать, когда каждый шард будет заполнен. В Atlas используйте автоматическое масштабирование кластера, чтобы автоматически добавлять хранилище или повышать уровень экземпляров при превышении порогов использования. Настройте оповещения Atlas для следующих случаев: использование диска выше 80%, загрузка CPU выше 70% более 1 часа и отставание репликации более 10 секунд. Проактивный мониторинг предотвращает авральные действия в 3 часа ночи.

// Capacity projection script
const avgDocBytes = 1024  // 1 KB average order document
const dailyOrders = 50000
const retentionDays = 365 * 3  // 3 years

const totalOrders = dailyOrders * retentionDays
const totalBytes = totalOrders * avgDocBytes
const totalGB = totalBytes / 1e9

console.log('Projected orders:', totalOrders.toLocaleString())
console.log('Projected storage:', totalGB.toFixed(0), 'GB')
// Add 3x for indexes + WiredTiger overhead
console.log('Recommended disk:', (totalGB * 3).toFixed(0), 'GB')

Шардированные кластеры Atlas и самостоятельное размещение

Atlas автоматически управляет всей инфраструктурой шардинга: разворачивает маршрутизаторы mongos, серверы конфигурации и наборы реплик шардов, балансирует чанки и устанавливает исправления для кластера. В самостоятельно размещённых системах каждый компонент необходимо вручную развернуть, контролировать и обслуживать — это создаёт значительную операционную нагрузку. Для большинства команд экономия на эксплуатации при использовании шардинга Atlas оправдывает его более высокую стоимость по сравнению с самостоятельным размещением, если только требования соответствия нормативам не требуют размещения в собственной инфраструктуре.

Быстрая проверка

Проверьте своё понимание концепций MongoDB и баз данных NoSQL из этого урока.

Итоги урока

В этом уроке вы узнали, что перед переходом к шардингу следует сначала масштабировать систему вертикально и использовать чтение со вторичных узлов — шардинг значительно усложняет систему, хотя большинству приложений он никогда не требуется; при выборе ключа шардинга нужно найти баланс между распределением операций записи (хеширование) и адресацией запросов (диапазоны); а целевые запросы, содержащие ключ шардинга, направляются на один шард, тогда как запросы с рассылкой по всем шардам обращаются ко всем шардам и требуют значительных ресурсов. Далее мы завершим итоговый проект: усилим безопасность и пройдём контрольный список готовности к эксплуатации.

Можно начать бесплатно

Изучай JavaScript с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
30
Уроки
120

Часто задаваемые вопросы

Урок «План масштабирования: от набора реплик до сегментированного кластера» бесплатный?

Да — полный текст урока «План масштабирования: от набора реплик до сегментированного кластера» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс MongoDB Academy, подпишись на CoddyKit PRO. Курс MongoDB Academy содержит 4 уроков всего.

Чему я научусь в уроке «План масштабирования: от набора реплик до сегментированного кластера»?

Учащиеся составят план ресурсов и выберут ключ сегмента, поддерживающий распределение чтения и записи приложения без создания перегруженных участков. Ты практикуешь MongoDB Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать MongoDB Academy?

Предыдущий опыт не требуется. MongoDB Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «План масштабирования: от набора реплик до сегментированного кластера»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке MongoDB Academy?

Да. Каждый урок MongoDB Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Анализ требований и проектирование схемы
  2. Стратегия индексации и проверка планировщика запросов
  3. План масштабирования: от набора реплик до сегментированного кластера
  4. Усиление безопасности и контрольный список для рабочей среды
← Назад к MongoDB Academy