Шардирование базы данных
Шардирование горизонтально делит строки между независимыми узлами. Это не то же самое, что репликация: реплика хранит копию, shard — отдельную часть набора.
flowchart TD A["Запрос приложения"] --> R["Маршрутизатор"] R --> S1["Shard 1: users 0..N"] R --> S2["Shard 2: users N..M"] R --> S3["Shard 3: users M.."]
Ключ шардирования
Ключ определяет размещение и маршрутизацию. Для заказов часто рассматривают user_id, чтобы пользователь и его заказы попадали в один shard.
Хороший ключ:
- равномерно распределяет данные и нагрузку;
- присутствует в большинстве запросов;
- позволяет держать связанные данные рядом;
- стабилен;
- не создает «горячий» shard.
Стратегии
Hash
shard = hash(user_id) mod shard_countРаспределение обычно ровное, но изменение количества shard требует consistent hashing, виртуальных bucket или миграции многих строк.
Range
Диапазоны удобны для последовательных данных и range-query, но монотонный ключ может направить новые записи в один горячий shard.
Directory
Отдельная таблица/сервис хранит отображение key -> shard. Гибко, но каталог становится критической зависимостью.
Что усложняется
- join и транзакции между shard;
- глобальные
UNIQUE, счетчики и последовательности; - сортировка, агрегация и пагинация по всем shard;
- изменение схемы и backup/restore;
- перенос горячего диапазона;
- наблюдаемость и балансировка.
Scatter-gather запрос отправляется всем shard, а затем объединяет ответы. Его latency определяется медленным участником, а стоимость растет с числом shard.
Глобальный идентификатор
Варианты: UUID, диапазоны на shard, идентификатор с частью времени/узла, централизованный генератор. Нужно учитывать уникальность, размер индекса, локальность вставки и утечку информации.
Когда не надо
Сначала обычно используют подходящую схему, индексы, partitioning внутри узла, read replicas, архивирование и вертикальное масштабирование. Шардирование оправдано, когда один узел действительно стал пределом по данным или записи и есть команда для эксплуатации распределенной системы.
Связано: Индексы SQL, Транзакции принцип ACID, Оперативная обработка транзакций, Микросервисная архитектура.
Вопросы
Чем shard отличается от replica? Shard хранит часть данных, replica — копию данных другого узла.
Какой главный критерий ключа? Он должен одновременно распределять нагрузку и локализовать основные запросы.
Почему hash(id) % N мешает масштабированию? При изменении N большинство ключей меняет shard.
Что такое scatter-gather? Запрос ко всем shard с объединением результатов.
Почему глобальный UNIQUE сложен? Проверка требует общего координатора или конструкции идентификатора, гарантирующей уникальность.