Databases

Шардирование

Шардирование — разрезание одной базы данных на части (шарды), которые живут на разных серверах и вместе образуют полный набор данных.

Что такое шардирование

Шардирование (sharding, шардинг) — разделение одной логической базы данных на части, размещённые на разных серверах. Каждая такая часть называется шардом и содержит свой кусок данных; вместе шарды составляют полный набор.

Шард — это не копия, а фрагмент. Пользователи с id от 1 до 1 000 000 лежат на шарде 1, от 1 000 001 до 2 000 000 — на шарде 2. Ни на одном сервере нет всех данных, и в этом смысл: снимается ограничение одной машины по объёму диска, памяти и скорости записи.

Слово происходит от английского shard — осколок, черепок.

Шардирование, репликация и партиционирование

Три понятия, которые постоянно смешивают:

Что делает Что решает
Репликация Копирует все данные на другие серверы Отказоустойчивость, масштаб чтения
Партиционирование Режет таблицу на части внутри одного сервера Управляемость, скорость сканов
Шардирование Режет данные между разными серверами Масштаб записи и объёма

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

Партиционирование — то, что стоит попробовать раньше шардирования. В PostgreSQL декларативные партиции по дате решают большинство задач с большими таблицами, не вводя распределённой системы:

CREATE TABLE events (id bigserial, ts timestamptz, payload jsonb)
PARTITION BY RANGE (ts);

CREATE TABLE events_2026_07 PARTITION OF events
  FOR VALUES FROM ('2026-07-01') TO ('2026-08-01');

Ключ шардирования

Shard key — колонка, по значению которой определяется шард строки. Это единственное по-настоящему важное решение, и оно почти необратимо: смена ключа означает перераспределение всех данных.

Стратегия Как работает Плюсы Минусы
По диапазону id 1–1M → шард 1 Простая, range-запросы работают Перекос: новые данные все в последний шард
По хешу hash(user_id) % N Равномерное распределение Range-запросы идут во все шарды
По справочнику Таблица соответствий Гибко, можно двигать точечно Справочник — узкое место
Географически По региону клиента Данные близко к пользователю, 152-ФЗ Неравномерность регионов

Хороший ключ обладает тремя свойствами: высокая кардинальность, равномерность распределения и присутствие в большинстве запросов. Классические ошибки — шардировать по дате создания (вся запись валится в последний шард, остальные простаивают) или по полю с малым числом значений вроде status.

Отдельная беда — hot shard: один крупный клиент генерирует больше нагрузки, чем весь остальной шард. Поэтому шардирование по tenant_id в мультитенантной системе требует плана на случай, когда один арендатор перерастёт машину.

Проблема % N

Наивная схема hash(key) % 4 ломается при добавлении пятого сервера: % 5 даёт другой остаток почти для всех ключей, и переезжать должны почти все данные. Решения — консистентное хеширование (при добавлении узла двигается ~1/N данных) либо виртуальные шарды: сразу нарезать данные на 1024 логических шарда и раскладывать их по физическим серверам пачками. Второе проще и потому распространено: рост кластера превращается в перенос части виртуальных шардов.

Что ломается после шардирования

Цена решения — приложение перестаёт работать с базой как с единым целым:

  • JOIN между шардами. Соединить таблицы, лежащие на разных серверах, штатным SQL нельзя. Данные либо денормализуют, либо собирают в коде.
  • Транзакции. ACID в пределах шарда — да; через несколько шардов — только двухфазный коммит со всеми его издержками.
  • Уникальность. AUTO_INCREMENT независим на каждом шарде. Нужны UUID или генератор вроде Snowflake.
  • Агрегаты. COUNT, SUM, ORDER BY ... LIMIT по всей базе — это запрос во все шарды и сборка результата.
  • Схема. Миграции надо накатить на каждый шард и пережить состояние, когда часть шардов уже обновлена, а часть ещё нет.
  • Эксплуатация. Бэкапы, мониторинг и восстановление — теперь для N серверов, причём консистентно между ними.

Когда шардировать

Шардирование — последнее средство, а не первое. Сначала честно проходят более дешёвые шаги: индексы и оптимизация запросов, вертикальный рост сервера, кеш перед базой, вынос чтения на реплики, партиционирование, вынос аналитики в ClickHouse. Каждый из них проще эксплуатировать, чем распределённую базу.

Реальные поводы: объём данных не влезает на самый большой доступный сервер; поток записи упирается в один узел (реплики тут не спасают — пишем всё равно в primary); требования по географии.

Готовые решения

  • MongoDB — sharded cluster встроен, распределением занимается mongos.
  • Citus — расширение PostgreSQL, превращающее его в распределённую БД.
  • Vitess — шардирование MySQL, выросшее из YouTube.
  • Redis Cluster — 16384 хеш-слота между узлами.
  • ClickHouse — распределённые таблицы поверх шардов.

Использовать готовое почти всегда разумнее, чем писать роутинг по шардам в приложении: логика выбора шарда, ребалансировка и отказоустойчивость там уже продуманы.

Связанные термины

Готовы запустить GPU-задачу?

Запустить GPU-сервер