Ответ
Репликация и шардирование — это две основные стратегии масштабирования баз данных, решающие разные проблемы.
Репликация (Replication)
- Что это: Создание и поддержание полных копий (реплик) набора данных на нескольких серверах.
- Цель: Обеспечение доступности (availability) и отказоустойчивости (fault tolerance). Если один сервер падает, другой может продолжить обслуживать запросы.
- Типы:
- Master-Slave (Primary-Secondary): Запись только на мастер, чтение с мастера и реплик.
- Multi-Master: Запись возможна в любую реплику, что сложнее в поддержании согласованности.
- Эффект на нагрузку: Позволяет масштабировать чтение, распределяя read-запросы по репликам. Не масштабирует запись — все записи должны быть применены на каждой реплике.
Пример настройки репликации в PostgreSQL:
-- На primary-сервере создаем пользователя для репликации
CREATE USER replicator WITH REPLICATION ENCRYPTED PASSWORD 'secret';
-- В pg_hba.conf добавляем запись для хоста-реплики
host replication replicator <replica_ip>/32 md5
-- На replica-сервере инициируем процесс копирования данных
pg_basebackup -h <primary_ip> -D /var/lib/postgresql/data -U replicator -P -R
Шардирование (Sharding / Partitioning)
- Что это: Горизонтальное разделение данных на части (шарды) и распределение этих частей по разным серверам.
- Цель: Обеспечение масштабируемости (scalability). Позволяет распределить и нагрузку на запись, и нагрузку на чтение.
- Принцип: Каждый шард содержит только подмножество данных (например, пользователи с ID от 1 до 1млн на шарде A, от 1млн до 2млн на шарде B).
- Эффект на нагрузку: Масштабирует и запись, и чтение, так как операции распределяются по разным серверам. Усложняет выполнение запросов, затрагивающих несколько шардов (join, глобальная сортировка).
Концептуальный пример шардирования по диапазону ключа:
# Функция-роутер, определяющая, на какой шард отправить данные для user_id
def get_shard_for_user(user_id: int, total_shards: int) -> int:
return user_id % total_shards # Простейшая стратегия — хэш-шардирование
# Запись идет на конкретный шард
shard_index = get_shard_for_user(new_user.id, 4)
shard_connections[shard_index].execute("INSERT INTO users ...", data)
| Ключевые отличия: | Аспект | Репликация | Шардирование |
|---|---|---|---|
| Копии данных | Полные копии на каждом узле. | Уникальные части данных на каждом узле. | |
| Основная цель | Отказоустойчивость, доступность. | Масштабируемость производительности. | |
| Масштабирование | Только операций чтения. | И чтения, и записи. | |
| Сложность | Относительно проста в настройке. | Значительно сложнее (роутинг, балансировка, cross-shard queries). |
На практике эти подходы часто комбинируются: каждый шард может быть реплицирован для обеспечения его отказоустойчивости.