← Назад к вопросам

В чем разница между шардированием и репликацией в MongoDB?

2.8 Senior🔥 61 комментариев
#Архитектура и паттерны#Базы данных (NoSQL)

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между шардированием и репликацией в MongoDB

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

Репликация (Replication)

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

Как это работает:

  • Один сервер — Primary (главный), остальные — Secondary (вторичные)
  • Все записи происходят на Primary
  • Secondary копируют данные с Primary
  • Если Primary выходит из строя, Secondary автоматически становится новым Primary
Даннные: User collection

┌──────────────────┐
│   Primary        │
│  (читать/писать) │
│   [Alice, Bob]   │
└────────┬─────────┘
         │ replication
         ▼
┌──────────────────┐
│  Secondary #1    │
│  (только чтение) │
│   [Alice, Bob]   │
└──────────────────┘
         ▲
         │ replication
┌────────┴─────────┐
│  Secondary #2    │
│  (только чтение) │
│   [Alice, Bob]   │
└──────────────────┘

Характеристики репликации:

  • Все узлы содержат полную копию данных
  • Обеспечивает высокую доступность (HA)
  • Позволяет масштабировать чтение (читаем с Secondary)
  • Не масштабирует хранилище (каждый узел хранит полные данные)
  • Failover происходит автоматически

Python пример:

from pymongo import MongoClient
from pymongo.errors import ConnectionFailure

# Подключение к replica set
client = MongoClient([
    "mongodb://server1:27017",
    "mongodb://server2:27017",
    "mongodb://server3:27017"
], replicaSet="rs0")

db = client["mydb"]
users = db["users"]

# Запись всегда идет на Primary
users.insert_one({"name": "Alice"})

# Чтение может быть с Primary или Secondary
from pymongo.read_preferences import ReadPreference

# Читаем с Secondary (балансировка нагрузки чтения)
users_collection = db.get_collection(
    "users",
    read_preference=ReadPreference.SECONDARY_PREFERRED
)
for user in users_collection.find():
    print(user)

Шардирование (Sharding)

Шардирование — это горизонтальное разбиение данных на несколько серверов. Разные серверы содержат разные части данных.

Как это работает:

  • Данные разбиваются на основе shard key (ключ шардирования)
  • Каждый шард содержит подмножество данных
  • Запросы маршрутизируются на нужный шард через Mongos (маршрутизатор)
Users collection (100 млн документов)

UserId: 1-25 млн      UserId: 25-50 млн    UserId: 50-75 млн    UserId: 75-100 млн
┌─────────────────┐   ┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐
│   Shard 1       │   │   Shard 2        │  │   Shard 3        │  │   Shard 4        │
│ Alice, Bob...   │   │ Charlie, David..│  │ Eve, Frank...    │  │ George, Helen..  │
└─────────────────┘   └──────────────────┘  └──────────────────┘  └──────────────────┘
        ▲                     ▲                      ▲                      ▲
        └─────────────────────┼──────────────────────┼──────────────────────┘
                              │
                    ┌─────────▼──────────┐
                    │   Mongos           │
                    │   (Router)         │
                    │ Маршрутизирует     │
                    │ запросы на нужный  │
                    │ шард               │
                    └───────────────────┘

Характеристики шардирования:

  • Данные распределены между несколькими узлами
  • Масштабирует хранилище (больше узлов = больше места)
  • Масштабирует пропускную способность (писать можно параллельно на разные шарды)
  • Требует правильного выбора shard key
  • Сложнее в управлении (балансировка шардов, jumbo chunks)
  • В каждом шарде может быть своя replica set

Python пример:

from pymongo import MongoClient

# Подключение к sharded cluster через mongos
client = MongoClient("mongodb://mongos1:27017,mongos2:27017")
db = client["mydb"]
users = db["users"]

# Включение шардирования для базы данных
# db.command("enableSharding", "mydb")

# Выбираем shard key (здесь userId)
# users.create_index([("userId", 1)])
# db.command("shardCollection", "mydb.users", key={"userId": 1})

# Вставка документов
for i in range(1000000):
    users.insert_one({"userId": i, "name": f"User{i}"})

# Поиск документа
# MongoDB автоматически определит, на каком шарде находится документ
user = users.find_one({"userId": 50000})
print(user)

# Запрос без shard key требует обращения ко всем шардам
for user in users.find({"name": "User123"}):
    print(user)  # Медленно! Требует scatter-gather

Сравнительная таблица

КритерийРепликацияШардирование
НазначениеВысокая доступностьМасштабирование хранилища
Данные на узлеПолная копияПодмножество (partition)
МасштабированиеМасштабирует чтениеМасштабирует чтение и запись
ХранилищеНе изменяетсяРастет с узлами
ОтказоустойчивостьДа (failover)Нет (потеря шарда = потеря данных)
СложностьПростаяСложная (shard key, балансировка)
Точка отказаPrimaryMongos, config servers
Когда использоватьДанные в пределах 1 сервераДанные > 1 сервера

Выбор shard key

Правильный shard key критичен для шардирования:

# ✅ Хороший shard key — распределяет данные равномерно
db.command("shardCollection", "mydb.users", key={"userId": 1})
# userId имеет высокую кардинальность и хорошо распределяет нагрузку

# ❌ Плохой shard key — неравномерное распределение
db.command("shardCollection", "mydb.users", key={"country": 1})
# Только несколько стран, один шард получит большинство данных (hot shard)

Когда использовать репликацию vs шардирование?

Используй репликацию, если:

  • Нужна высокая доступность
  • Данные помещаются на одном сервере
  • Нужно масштабировать чтение
  • Требуется автоматический failover

Используй шардирование, если:

  • Данные превышают объем одного сервера
  • Нужно масштабировать запись
  • Данные логически разделяются (по userId, по租户 и т.д.)
  • Готов к сложности управления

В реальности: Обычно используется Replica Set + Sharding:

  • Каждый шард — это Replica Set для HA
  • Несколько шардов для масштабирования данных
  • Mongos маршрутизирует запросы
┌─────────────────────────────────────┐
│      Sharded Cluster                │
│                                     │
│  Shard 1 (Replica Set)  ┌─────────┐│
│  ┌─────────────────────┤ Mongos   ││
│  │ Primary, 2ndary     │ Router   ││
│  └─────────────────────┤          ││
│                        └──▲─────┬─┘│
│  Shard 2 (Replica Set)    │     │   │
│  ┌─────────────────────┐  │     │   │
│  │ Primary, 2ndary     ├──┘     │   │
│  └─────────────────────┘        │   │
│                                 │   │
│  Shard 3 (Replica Set)          │   │
│  ┌─────────────────────┐        │   │
│  │ Primary, 2ndary     ├────────┘   │
│  └─────────────────────┘            │
└─────────────────────────────────────┘

Этот подход дает и отказоустойчивость (репликация), и масштабируемость (шардирование).