Всем привет! И снова с вами Илья Криволапов – системный аналитик в SENSE, где мы вместе с командой трудимся над проектом одного из цветных банков РФ. Напоминаю, что в профессии я уже больше пяти лет и, несмотря на фамилию, прод все еще живой и здоровый (ну почти)!

В свободное от работы время, я преподаю курс «Хранение и обработка больших объемов данных», где успел накопить немало наблюдений, кейсов и выводов, которые не хочется держать в столе. Поэтому всё самое полезное оформил в цикл статей на Хабре – рассказываю как строить базы данных с прицелом на рост и не сойти с ума под нагрузкой.

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

Материал будет полезен всем, кто проектирует, масштабирует или просто поддерживает «здоровье» базы данных: DBA, архитекторам, DevOps-инженерам, аналитикам и разработчикам.

Финальный рывок — поехали!


4. Директивный шардинг: «ручное управление» распределения данных

Представьте библиотеку, где книги расставлены не по алфавиту или жанрам, а согласно личному указанию библиотекаря. Каждая книга получает «прописку» на конкретной полке, записанную в специальной тетради. Это и есть директивный шардинг — гибкий, но требовательный метод распределения данных.

Ключ и каталог: как это работает?

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

Каталог (Lookup Table) — это «главная книга», где записано:

user123 → Шард 5  

order456 → Шард 2  

device789 → Шард 7  

Как почтовый индекс (да, снова эта метафора), но для данных.

Как система находит нужный шард?

  1. Запрос приходит с ключом (например, user123);

  2. Координатор заглядывает в каталог и узнаёт: «Ага, user123 лежит в Шарде 5»;

  3. Запрос направляется в нужный шард.

Варианты хранения каталога:

  • Централизованная таблица — проще, но если она «упадет», система перестанет работать;

  • Распределенное хранилище (например, Redis) — надежнее, но сложнее;

  • Кэш — часто используемые записи хранятся «под рукой» для быстрого доступа.

Плюсы и минусы: когда выбирать?

Подойдет, если важны:

✅ Полная гибкость
— можно распределять данные как угодно, даже по бизнес-логике (например, VIP-клиенты — в отдельный шард);
✅ Легкая миграция — чтобы переместить данные, достаточно обновить каталог;
✅ Поддержка сложных запросов — каталог может хранить дополнительную информацию для оптимизации.

Может принести с собой:

❗️ Каталог — единая точка отказа (если не распределен);
❗️Дополнительная задержка — каждый запрос требует обращения к каталогу;
❗️Сложность управления — каталог нужно поддерживать в актуальном состоянии.

Как бороться с проблемами?

  • Репликация каталога — чтобы избежать «падения»;

  • Кэширование — хранить популярные соответствия в памяти;

  • Иерархия каталогов — например, сначала искать по стране, потом по городу.

Где используют?

  • Системы идентификации (например, распределение пользователей по шардам);

  • Управление конфигурациями (какой сервер за что отвечает);

  • Маршрутизация сообщений;

  • Специализированные БД — где важно точное расположение данных.

Вывод: когда выбирать директивный шардинг?

✅ Подходит, если:

  • Нужна максимальная гибкость в распределении данных;

  • Данные часто перемещаются между шардами;

  • Можно позволить себе накладные расходы на каталог.

❗️ Не подходит, если:

  • Требуется максимальная производительность (лишние запросы к каталогу замедляют работу);

  • Нет ресурсов поддерживать каталог.

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

P.S. Часто комбинируют с другими методами — например, внутри шарда используют хэш-распределение.

5. Круговой метод шардинга: когда данные ходят по кругу

Представьте карусель с ячейками для хранения вещей где-нибудь в парке аттракционов. Когда появляется новый предмет, система находит для него ближайшую свободную ячейку. Если одну ячейку убирают — вещи просто переезжают в следующую по кругу. Это и есть круговой метод шардинга — умный способ распределять данные с минимальными переездами.

Круговая система распределения

Ключ — ID пользователя, хэш файла или любой другой идентификатор.

Кольцо хэшей — все возможные хэш-значения представлены как точки на круге (от 0 до 2³²-1). На этом кольце располагаются:

  • Серверы (шарды) — например, Сервер А → хэш 100, Сервер B → хэш 1000;

  • Данные — хэш ключа user123 = 500 → попадает на сервер B (первый встречный по часовой стрелке).

Как это работает?

  1. Добавление сервера (Сервер C с хэшом 700):

    • Переезжают только данные между 500 и 700 (раньше они шли на B, теперь на C);

    • Остальные данные остаются на месте!

  2. Удаление сервера (Сервер B пропал, кто остался на трубе?):

    • Его данные (500-1000) переходят к следующему — Серверу A.

Компоненты:

  • Хэш-функция — равномерно распределяет серверы и данные по кольцу (например, SHA-1);

  • Координатор — быстро находит «следующий сервер» для каждого ключа.

Плюсы и минусы

Подойдет, если важны:

Минимум переездов — при изменении числа серверов затрагивается мало данных;
Масштабируемость — добавление 1 сервера = O(1/N) перемещений (N — общее число серверов);
Отказоустойчивость — если сервер падает, его данные автоматически переходят к соседу.

Может принести с собой:

❗️Риск неравномерности — серверы могут случайно сгруппироваться на кольце, получив разную нагрузку;
❗️ Сложнее, чем обычное хэширование — нужно реализовывать виртуальные узлы.

Как улучшить балансировку?

Виртуальные узлы — один физический сервер представляется множеством точек на кольце (например, 1000 виртуальных узлов для каждого сервера). Это:

  • Уменьшает «провалы» в распределении;

  • Позволяет давать мощным серверам больше виртуальных узлов.

Пример:

Сервер A → виртуальные узлы 50, 150, 250...  

Сервер B → 1000, 1100, 1200...  

Где используют?

  • CDN-системы (Например, Cloudflare, Akamai) — распределяют контент по серверам;

  • NoSQL БД (Например, Cassandra, DynamoDB) — шардирование данных;

  • Кэши (Например, Redis, Memcached) — хранение ключей в кластере;

  • Очереди (И по классике, к примеру, Kafka) — балансировка партиций.

Вывод: когда выбирать круговой метод?

✅ Подходит, если:

  • Часто меняется количество серверов;

  • Важна минимальная миграция данных (например, в реальном времени);

  • Нужна отказоустойчивость.

❗️ Не подходит, если:

  • Система очень простая (избыточная сложность);

  • Данные требуют жесткой привязки к локации (лучше подойдёт геошардирование) или к какому-либо другому параметру.

Круговой метод шардирования — как умная карусель: добавь или убери одну лошадку — и только несколько детей придётся пересадить. 

P.S. Для идеального баланса используйте 100-1000 виртуальных узлов на сервер — это устранит неравномерность.

6. Динамический шардинг: когда база данных живёт своей жизнью

Представьте умный склад, который сам реорганизует полки (Возможно, прямо сейчас Amazon проектирует это): когда одни товары заканчиваются — объединяет секции, когда другие заполняются — разделяет их. Это и есть динамический шардинг — система, которая автоматически подстраивается под ваши данные без ручного вмешательства.

Как это работает?

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

Автопилот системы постоянно следит за:

  • Размером шардов (не превратился ли в слона);

  • Нагрузкой (не много ли посуды в лавке);

  • Распределением данных (нет ли слишком заполненных или пустых полок в нашей метафорической посудной лавке).

При проблемах система сама решает:

  • Разделить шард → если стал слишком большим;

  • Объединить шарды → если оба полупустые;

  • Перераспределить данные → чтобы выровнять нагрузку.

Архитектура: из чего состоит и кто за что отвечает?

  • Мониторинг — как «врач», проверяет пульс системы (метрики);

  • Аналитический модуль — «мозг», решает: резать или склеивать;

  • Менеджер шардов — «строитель», выполняет решения аналитического модуля;

  • Координатор — «регулировщик», направляет запросы по новым правилам.

Пример:

Шард А вырос до 1 ТБ → Аналитик: «Делись на два!».

Менеджер создаёт Шард А1 и А2, а затем переносит данные.

Координатор теперь знает, куда направлять запросы.

Плюсы и минусы

Подойдет, если важны:

Автомасштабирование — система растет и сжимается сама;
Оптимальное использование ресурсов — нет «пустых» или перегруженных шардов;
Меньше головной боли — не нужно вручную переделывать схему.

Может принести с собой:

❗️ Сложная реализация — нужны умные и в идеале работающие алгоритмы перераспределения;
❗️ Дополнительные расходы — мониторинг и частая автоматическая перебалансировка требуют ресурсов;
❗️ Риск «дерганий» — если настройки плохие, шарды будут постоянно делиться/сливаться.

Как избежать проблем?

  • Пороговые значения — «разделять, только если >1 ТБ»;

  • Постепенная миграция — переезжать маленькими порциями;

  • Режим «энергосбережения» — не трогать шарды в часы пик.

Где используют?

  • Облачные БД (MongoDB Atlas, Amazon DynamoDB) — чтобы снять с клиентов головную боль по проведению масштабирования;

  • Крупные маркетплейсы — когда количество товаров и заказов меняется ежечасно;

  • Аналитические системы — где данные могут внезапно «взрываться» в объёме.

Вывод: когда выбирать динамический шардинг?

Подходит, если:

  • Данные растут непредсказуемо;

  • Нет желания/возможности управлять шардами вручную;

  • Можно позволить себе «умную» систему.

Не подходит, если:

  • Система маленькая и стабильная (избыточность);

  • Нет ресурсов на сложную реализацию;

  • Критичны наносекунды задержки (перебалансировки тормозят).

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

Четыре фатальные ошибки выбора ключа для любого метода шардирования

  1. Использование ключа с низким разнообразием: Например, поле типа "статус заказа» с двумя значениями («выполнено» и «в процессе»). Большинство записей окажется в одном шарде;

  2. Неучтенный будущий рост: Использование временного ключа (например, дата создания записи) может привести к постепенному смещению нагрузки на один шард, поскольку новые записи будут поступать туда же;

  3. Игнорирование бизнес-логики: Важно учитывать, какие запросы чаще всего выполняются и как данные используются в приложении. Например, если пользователи регулярно запрашивают данные по определённому региону, стоит сделать регион ключевым атрибутом для шардирования;

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

Почему шардинг — выбор технологических гигантов?

Линейная масштабируемость

Каждый новый шард добавляет ресурсы для хранения и обработки. Некоторые системы, к примеру, MongoDB Atlas и вовсе позволяет добавлять шарды без downtime.

Эффективное использование ресурсов

Нет необходимости держать все данные на каждом сервере. Это как вместо одного огромного склада использовать несколько специализированных. Вспоминаем отсылку к децентрализации Форда

Параллельная обработка

Запросы выполняются одновременно на разных шардах. 10 шардов = 10 параллельных потоков обработки.

Географическая оптимизация

Данные можно разместить физически ближе к пользователям, уменьшив задержки.

Тёмная сторона шардинга

❗️ Cross-shard транзакции
Операции, затрагивающие несколько шардов, в 10-100 раз медленнее локальных. Это как заказ из разных ресторанов — ждать придётся дольше и не факт, что напитки приедут вместе с основным блюдом.

❗️ Горячие шарды
Неравномерное распределение нагрузки:

  • 1 шард: 90% запросов

  • Остальные: 10%

❗️ Сложность миграции
Перенос данных между шардами требует тщательного планирования. Это как переезд магазина без остановки продаж. Дико, страшно, но нужно.

❗️ Потеря гибкости запросов
JOIN между шардами работают крайне плохо. Приходится денормализовать данные. 

Антипаттерны шардинга: как НЕ надо делать

1. Шардинг без необходимости

Проблема:
Разделили маленькую БД на 10 шардов "на будущее»
Последствия:

  • 10x сложность администрирования

  • Запросы стали медленнее

Решение:
Шардить только при >500GB данных или >10K RPS (запросов в секунду)

2. Игнорирование транзакций

Проблема:
Платежная система с шардингом по user_id
Последствия:
Переводы между пользователями на разных шардах занимают 5+ секунд
Решение:

  • Локализовать связанные данные (например, по стране)

  • Использовать SAGA-паттерн

3. Ручная балансировка

Проблема:
Администратор вручную перераспределяет данные раз в квартал
Последствия:

  • 80% нагрузки на 3 из 20 шардов

  • Постоянные проблемы с производительностью

Решение:
Автоматический балансировщик (привет, динамическое шардирование!)

4. Слепое копирование архитектуры

Проблема:
Скопировали шардинг Facebook для маленького SaaS
Последствия:

  • 90% шардов простаивают

  • Сложность не оправдана масштабом

Решение:
Начинать с простой репликации, добавлять шардинг по мере роста

5. Отсутствие плана миграции

Проблема:
Шардинг внедряется в панике при уже начавшихся проблемах
Последствия:

  • Недели простоя

  • Потеря данных при переходе

Решение:
Грамотно-спроектированное решение в самом начале процесса разработки системы. Это важно. Всегда держите в голове дальнейшее возможное масштабирование.

Итог

Вот мы и добрались до финала. За три части мы прошли длинный путь от базовых подходов к масштабированию до вполне конкретных техник шардирования, которые помогают справляться с ростом нагрузки и объёма данных. Спасибо, что читали весь цикл. Надеюсь, он был полезен и хотя бы немного помог вам посмотреть на архитектуру баз данных под другим углом.

А теперь слово вам. С какими проблемами в масштабировании баз данных вам приходилось сталкиваться? Какие инструменты используете?

Делитесь своими кейсами в комментариях — обсудим, сравним и, возможно, подскажем друг другу полезные решения.

Комментарии (0)