← Назад к вопросам
В чем разница между реплицированием и шардированием?
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, PostgreSQL | MongoDB, 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, масштаб хранения)