Всем привет! И снова с вами Илья Криволапов – системный аналитик в SENSE, где мы вместе с командой трудимся над проектом одного из цветных банков РФ. Напоминаю, что в профессии я уже больше пяти лет и, несмотря на фамилию, прод все еще живой и здоровый (ну почти)!
В свободное от работы время, я преподаю курс «Хранение и обработка больших объемов данных», где успел накопить немало наблюдений, кейсов и выводов, которые не хочется держать в столе. Поэтому всё самое полезное оформил в цикл статей на Хабре – рассказываю как строить базы данных с прицелом на рост и не сойти с ума под нагрузкой.
В первой части мы говорили о базовых стратегиях масштабирования: вертикальной и горизонтальной. Покрутили в руках репликацию, рассмотрели кейсы, когда и как можно к ней обращаться. Во второй углубились в шардинг и разобрали три популярных подхода: по диапазону, хэшу и геозонам. А сегодня будет финальная, третья часть. В ней мы рассмотрим ещё три способа шардирования: директивный, круговой и динамический. Расскажу, как они устроены, когда применяются, в чём их сильные стороны и где скрывается подвох.
Материал будет полезен всем, кто проектирует, масштабирует или просто поддерживает «здоровье» базы данных: DBA, архитекторам, DevOps-инженерам, аналитикам и разработчикам.
Финальный рывок — поехали!
4. Директивный шардинг: «ручное управление» распределения данных
Представьте библиотеку, где книги расставлены не по алфавиту или жанрам, а согласно личному указанию библиотекаря. Каждая книга получает «прописку» на конкретной полке, записанную в специальной тетради. Это и есть директивный шардинг — гибкий, но требовательный метод распределения данных.
Ключ и каталог: как это работает?
Ключ — может быть любым (ID пользователя, email, номер заказа). В отличие от других методов, здесь нет жестких правил распределения — всё решает каталог.
Каталог (Lookup Table) — это «главная книга», где записано:
user123 → Шард 5
order456 → Шард 2
device789 → Шард 7
Как почтовый индекс (да, снова эта метафора), но для данных.
Как система находит нужный шард?
Запрос приходит с ключом (например, user123);
Координатор заглядывает в каталог и узнаёт: «Ага, user123 лежит в Шарде 5»;
Запрос направляется в нужный шард.
Варианты хранения каталога:
Централизованная таблица — проще, но если она «упадет», система перестанет работать;
Распределенное хранилище (например, Redis) — надежнее, но сложнее;
Кэш — часто используемые записи хранятся «под рукой» для быстрого доступа.
Плюсы и минусы: когда выбирать?
Подойдет, если важны:
✅ Полная гибкость — можно распределять данные как угодно, даже по бизнес-логике (например, VIP-клиенты — в отдельный шард);
✅ Легкая миграция — чтобы переместить данные, достаточно обновить каталог;
✅ Поддержка сложных запросов — каталог может хранить дополнительную информацию для оптимизации.
Может принести с собой:
❗️ Каталог — единая точка отказа (если не распределен);
❗️Дополнительная задержка — каждый запрос требует обращения к каталогу;
❗️Сложность управления — каталог нужно поддерживать в актуальном состоянии.
Как бороться с проблемами?
Репликация каталога — чтобы избежать «падения»;
Кэширование — хранить популярные соответствия в памяти;
Иерархия каталогов — например, сначала искать по стране, потом по городу.
Где используют?
Системы идентификации (например, распределение пользователей по шардам);
Управление конфигурациями (какой сервер за что отвечает);
Маршрутизация сообщений;
Специализированные БД — где важно точное расположение данных.
Вывод: когда выбирать директивный шардинг?
✅ Подходит, если:
Нужна максимальная гибкость в распределении данных;
Данные часто перемещаются между шардами;
Можно позволить себе накладные расходы на каталог.
❗️ Не подходит, если:
Требуется максимальная производительность (лишние запросы к каталогу замедляют работу);
Нет ресурсов поддерживать каталог.
Директивный шардинг — как ручное управление светофорами в городе: можно тонко настроить под любые условия, но без грамотного диспетчера будут пробки.
P.S. Часто комбинируют с другими методами — например, внутри шарда используют хэш-распределение.

5. Круговой метод шардинга: когда данные ходят по кругу
Представьте карусель с ячейками для хранения вещей где-нибудь в парке аттракционов. Когда появляется новый предмет, система находит для него ближайшую свободную ячейку. Если одну ячейку убирают — вещи просто переезжают в следующую по кругу. Это и есть круговой метод шардинга — умный способ распределять данные с минимальными переездами.
Круговая система распределения
Ключ — ID пользователя, хэш файла или любой другой идентификатор.
Кольцо хэшей — все возможные хэш-значения представлены как точки на круге (от 0 до 2³²-1). На этом кольце располагаются:
Серверы (шарды) — например, Сервер А → хэш 100, Сервер B → хэш 1000;
Данные — хэш ключа user123 = 500 → попадает на сервер B (первый встречный по часовой стрелке).
Как это работает?
-
Добавление сервера (Сервер C с хэшом 700):
Переезжают только данные между 500 и 700 (раньше они шли на B, теперь на C);
Остальные данные остаются на месте!
-
Удаление сервера (Сервер 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) — чтобы снять с клиентов головную боль по проведению масштабирования;
Крупные маркетплейсы — когда количество товаров и заказов меняется ежечасно;
Аналитические системы — где данные могут внезапно «взрываться» в объёме.
Вывод: когда выбирать динамический шардинг?
Подходит, если:
Данные растут непредсказуемо;
Нет желания/возможности управлять шардами вручную;
Можно позволить себе «умную» систему.
Не подходит, если:
Система маленькая и стабильная (избыточность);
Нет ресурсов на сложную реализацию;
Критичны наносекунды задержки (перебалансировки тормозят).

Динамический шардинг — как робот-пылесос с настроенным временем уборки: сам знает, когда пропылесосить и какой режим выбрать. Но если дать ему плохие инструкции — будет носиться без толку.
Четыре фатальные ошибки выбора ключа для любого метода шардирования
Использование ключа с низким разнообразием: Например, поле типа "статус заказа» с двумя значениями («выполнено» и «в процессе»). Большинство записей окажется в одном шарде;
Неучтенный будущий рост: Использование временного ключа (например, дата создания записи) может привести к постепенному смещению нагрузки на один шард, поскольку новые записи будут поступать туда же;
Игнорирование бизнес-логики: Важно учитывать, какие запросы чаще всего выполняются и как данные используются в приложении. Например, если пользователи регулярно запрашивают данные по определённому региону, стоит сделать регион ключевым атрибутом для шардирования;
Чрезмерный акцент на производительность чтения: Иногда ради оптимизации скорости чтения забывают о балансе между чтением и записью, что ведёт к проблемам с равномерностью нагрузки.
Почему шардинг — выбор технологических гигантов?
✅ Линейная масштабируемость
Каждый новый шард добавляет ресурсы для хранения и обработки. Некоторые системы, к примеру, 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. Отсутствие плана миграции
Проблема:
Шардинг внедряется в панике при уже начавшихся проблемах
Последствия:
Недели простоя
Потеря данных при переходе
Решение:
Грамотно-спроектированное решение в самом начале процесса разработки системы. Это важно. Всегда держите в голове дальнейшее возможное масштабирование.
Итог
Вот мы и добрались до финала. За три части мы прошли длинный путь от базовых подходов к масштабированию до вполне конкретных техник шардирования, которые помогают справляться с ростом нагрузки и объёма данных. Спасибо, что читали весь цикл. Надеюсь, он был полезен и хотя бы немного помог вам посмотреть на архитектуру баз данных под другим углом.
А теперь слово вам. С какими проблемами в масштабировании баз данных вам приходилось сталкиваться? Какие инструменты используете?
Делитесь своими кейсами в комментариях — обсудим, сравним и, возможно, подскажем друг другу полезные решения.