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

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

2.3 Middle🔥 151 комментариев
#Big Data и распределенные вычисления#SQL и базы данных

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

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

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

Репликация vs Шардирование

Оба метода масштабируют БД, но решают разные проблемы.

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

Что делает: копирует ОДНИ И ТЕ ЖЕ данные на несколько серверов.

Мастер (write)           Мастер (write)
  |                        |
  v                        v
 Slave 1 (read)      Slave 2 (read)
  |                        |
  v                        v
 Slave 3 (read)      Slave 4 (read)

Все копии содержат ПОЛНЫЕ ОДИНАКОВЫЕ данные

Цель:

  • Высокая доступность (если мастер упал, берём slave)
  • Распределение нагрузки чтения (читаем со slaves)
  • Резервная копия (slave содержит все данные)

Примеры:

# PostgreSQL репликация
insert_count = master_db.insert(data)  # пишем в мастер
read_data = slave_db.select(query)     # читаем из slave

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

Что делает: разбивает данные НА РАЗНЫЕ СЕРВЕРЫ по ключу.

Пользователи ID 1-1000      Пользователи ID 1001-2000
    Шард 1                       Шард 2
  +---------+                  +---------+
  | User 1  |                  | User 1001 |
  | User 2  |                  | User 1002 |
  | User 500|                  | User 2000 |
  +---------+                  +---------+

Каждый шард содержит ЧАСТЬ данных (в разных серверах)

Цель:

  • Горизонтальное масштабирование (делим данные между серверами)
  • Уменьшение нагрузки на один сервер
  • Работа с большими объёмами данных

Примеры:

# Шардирование по user_id
user_id = 1234
shard_key = user_id % num_shards  # shard_key = 2
shard_db = shards[shard_key]  # выбираем сервер 2
data = shard_db.select(f"SELECT * FROM users WHERE user_id = {user_id}")

# Другой юзер
user_id = 5678
shard_key = user_id % num_shards  # shard_key = 0
shard_db = shards[shard_key]  # выбираем сервер 0

Сравнение

АспектРепликацияШардирование
Что копируетсяВСЕ данныеЧАСТЬ данных
ЗачемДоступность, читаемостьМасштабируемость
Количество копий3-5 копий одних данных1 копия на шард
Размер на сервереПОЛНЫЙ датасетЧАСТЬ датасета
МасштабированиеВертикальное (сильнее аппарат)Горизонтальное (больше серверов)
Проблема если упадёт серверЕсть копия (другой slave/мастер)Потеряется часть данных
ПримерыMySQL Master-Slave, PostgreSQLMongoDB, Cassandra, Elasticsearch

Практические примеры

Репликация

from sqlalchemy import create_engine

# Мастер (пишу сюда)
master_db = create_engine("postgresql://master-server/db")

# Slave 1 (читаю отсюда)
slave1_db = create_engine("postgresql://slave1-server/db")

# Slave 2 (читаю отсюда для балансировки)
slave2_db = create_engine("postgresql://slave2-server/db")

# Запись
master_db.execute("INSERT INTO users VALUES (1, Alice, alice@mail.com)")
# Репликируется автоматически на slave1 и slave2 с задержкой

# Чтение (распределяем нагрузку)
for i in range(1000):
    data = slave1_db.execute("SELECT * FROM users WHERE id = ?", (i,))
    # или
    data = slave2_db.execute("SELECT * FROM users WHERE id = ?", (i,))

Шардирование

# Шардирование по user_id
num_shards = 4
shards = [
    create_engine("postgresql://shard0-server/db"),
    create_engine("postgresql://shard1-server/db"),
    create_engine("postgresql://shard2-server/db"),
    create_engine("postgresql://shard3-server/db"),
]

def get_shard_for_user(user_id):
    return shards[user_id % num_shards]

# Вставка юзера 101
user_id = 101
shard = get_shard_for_user(user_id)  # shard = shards[1]
shard.execute(
    "INSERT INTO users (id, name) VALUES (?, ?)",
    (user_id, "Bob")
)

# Вставка юзера 205
user_id = 205
shard = get_shard_for_user(user_id)  # shard = shards[1] (тоже!)
shard.execute(
    "INSERT INTO users (id, name) VALUES (?, ?)",
    (user_id, "Charlie")
)

Когда использовать

Репликация

✅ Используй если:

  • Много операций ЧТЕНИЯ (больше 80% запросов)
  • Нужна высокая доступность (отказоустойчивость)
  • Один датасет, который полностью помещается на сервер
  • Есть выделенный мастер для записей

Проблема: Репликация не решает problem of too much data for one server

Шардирование

✅ Используй если:

  • Датасет больше, чем может хранить один сервер
  • Нужно распределить НАГРУЗКУ между серверами
  • Есть natural key для шардирования (user_id, customer_id)
  • Готов к сложности (теперь нужно управлять несколькими шардами)

Проблема: Сложные cross-shard запросы становятся трудными.

Гибридный подход

Сочетай оба метода!

Шард 1 Мастер       Шард 2 Мастер
    |                    |
    +----+           +----+
    |    |           |    |
  Slave Slave      Slave Slave

Каждый шард имеет СВОЮ репликацию
- Шард 1 обрабатывает users 1-500
- Шард 2 обрабатывает users 501-1000
- У каждого шарда есть мастер и slaves для масштабирования чтения

Сложные запросы

В реплицированной БД (просто)

SELECT u.name, COUNT(o.id) as orders
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id
-- Все данные на одном сервере → простой запрос

В шардированной БД (сложно)

# Нужно запросить РАЗНЫЕ шарды и объединить результаты
results = []
for shard in shards:
    data = shard.execute("SELECT name, order_count FROM users_stats")
    results.extend(data)

# Объединяем результаты из всех шардов
final_result = aggregate(results)

Вывод

ПроблемаРешение
Один сервер может упастьРепликация ✓
Много читов, но мало писейРепликация ✓
Данные не влезают в один серверШардирование ✓
Большая нагрузка на один серверШардирование ✓
И то, и другоеРепликация + Шардирование ✓

Репликация = масштабирование читов (vertical scaling, масштаб доступности) Шардирование = масштабирование данных (horizontal scaling, масштаб хранения)

В чем разница между реплицированием и шардированием? | PrepBro