Шардирование базы данных

Шардирование горизонтально делит строки между независимыми узлами. Это не то же самое, что репликация: реплика хранит копию, 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 сложен? Проверка требует общего координатора или конструкции идентификатора, гарантирующей уникальность.