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

«В чем разница между репликацией и шардированием в базах данных?» — вопрос из категории Базы данных, который задают на 26% собеседований Data Scientist / ML Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Репликация и шардирование — это две основные стратегии масштабирования баз данных, решающие разные проблемы.

Репликация (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).

На практике эти подходы часто комбинируются: каждый шард может быть реплицирован для обеспечения его отказоустойчивости.