Ответ
Шардирование (горизонтальное партиционирование) и репликация — это две ключевые техники масштабирования баз данных, решающие разные проблемы.
Репликация
- Цель: Повышение доступности (availability) и отказоустойчивости (fault tolerance), а также распределение нагрузки на чтение.
- Как работает: Создаются точные копии (реплики) набора данных на нескольких серверах.
- Модели:
- Master-Slave (Источник-Реplica): Запись только в мастер, чтение из мастер и реплик.
- Multi-Master: Запись в любой узел, с последующей синхронизацией между всеми.
- Преимущества: Отказоустойчивость (при падении мастера реплика становится новой мастер), географическое распределение, снижение нагрузки на мастер за счет чтения с реплик.
- Недостатки: Не решает проблему масштабирования записи, возможна задержка репликации (несогласованность данных).
Концептуальный пример:
-- Все узлы содержат ОДИН И ТОТ ЖЕ набор данных
-- Мастер-узел для записи
MASTER: INSERT INTO users (id, name) VALUES (1, 'Alice');
-- Реплики для чтения (данные появятся после синхронизации)
REPLICA_1: SELECT * FROM users; --> Возвращает Alice
REPLICA_2: SELECT * FROM users; --> Возвращает Alice
Шардирование
- Цель: Горизонтальное масштабирование (scaling out) для обработки больших объемов данных и высокой нагрузки на запись.
- Как работает: Набор данных разделяется (партиционируется) на меньшие части (шарды) по определенному ключу (например,
user_id), и каждый шард размещается на отдельном сервере. - Стратегии: По диапазону, по хешу, по списку.
- Преимущества: Масштабирование и записи, и чтения; работа с объемами данных, превышающими возможности одного сервера.
- Недостатки: Сложность: операции
JOINи транзакции, затрагивающие несколько шардов, становятся нетривиальными; неравномерное распределение нагрузки ("горячие" шарды).
Концептуальный пример (шардирование по user_id % 3):
-- Данные РАЗДЕЛЕНЫ между разными серверами
SHARD_0 (user_id % 3 = 0): SELECT * FROM users WHERE id = 3; --> Возвращает пользователя 3
SHARD_1 (user_id % 3 = 1): SELECT * FROM users WHERE id = 1; --> Возвращает пользователя 1
SHARD_2 (user_id % 3 = 2): SELECT * FROM users WHERE id = 2; --> Возвращает пользователя 2
-- Запрос, требующий данных со всех шардов, сложен:
-- SELECT * FROM users ORDER BY created_at; -- Нужно запрашивать все шарды и объединять
Сравнительная таблица
| Аспект | Репликация | Шардирование |
|---|---|---|
| Основная цель | Надежность и доступность | Масштабируемость (производительность) |
| Структура данных | Одинаковые данные на каждом узле | Разные данные на каждом узле |
| Масштабирование записи | Нет (запись обычно в один мастер) | Да (запись распределяется по шардам) |
| Масштабирование чтения | Да (чтение с реплик) | Да (чтение распределяется по шардам) |
| Сложность запросов | Низкая (данные локальны) | Высокая (межшардовые JOIN, агрегации) |
| Отказоустойчивость | Высокая (данные дублируются) | Зависит от реализации (потеря шарда = потеря части данных) |
Практическое применение
На практике эти техники часто комбинируются. Например:
- Сначала применяется шардирование для разделения данных.
- Затем каждый шард реплицируется (например, в конфигурации мастер-реплика) для обеспечения отказоустойчивости внутри шарда.
Таким образом, система получает преимущества обоих подходов: горизонтальную масштабируемость от шардирования и высокую доступность от репликации.