Всем привет! На связи снова Илья Криволапов — системный аналитик в SENSE, где мы трудимся на проекте одного из цветных банков РФ. Работаю в профессии уже пятый год и, несмотря на мою фамилию, с продом у нас в целом тёплые отношения.
Помимо боевых задач, я преподаю курс «Хранение и обработка больших объемов данных» и за это время накопил немало практических кейсов и наблюдений. Всё это добро я решил не держать при себе и собрал все самое полезное в виде ультимативного гайда по оптимизации и грамотному проектированию баз данных с расчетом на масштабирование, который публикую на Хабре.
Цикл состоит из 3 частей. В первой мы обсудили два базовых подхода к масштабированию БД: вертикальный и горизонтальный. Поговорили о плюсах, минусах и о том, как делать точно не стоит.
Во второй части – то есть сейчас – мы нырнём глубже в мир горизонтального масштабирования и разберем три первых способа шардирования: по диапазону, по хэшу и по географическим зонам. Я расскажу, как каждый из них работает, где пригодится и в каких случаях может дать сбой.
Материал по-прежнему будет полезен всем, кто заботится о «здоровье» базы данных: DBA, архитекторам, DevOps-инженерам, аналитикам и разработчикам.
Ах да, в комментариях к предыдущей статье коллеги советовали добавить во введение информацию о том, что статья написана простым языком, с приведением большого количества бытовых сравнений. Сделано это намеренно, для 100% понимания и раскрытия сути паттернов :)
Ну что же, готовы продолжать? Тогда поехали!
Что такое шардинг на практике?
Представьте, что ваша база данных — это переполненный склад. Репликация создала несколько копий этого склада, но товаров становится всё больше. Шардинг — это как разделить один огромный склад на специализированные помещения: один для электроники, другой для одежды, третий для продуктов.

Шардинг на практике – это метод горизонтального масштабирования, при котором данные разделяются на части (шарды) и распределяются между разными серверами. Каждый шард содержит только свою порцию данных.
Техническая аналогия:
Если репликация — это копирование всей книги, то шардинг — это разделение книги на главы и распределение их между разными библиотеками.
Основные типы шардинга:
1. Хэш-шардирование: когда данные делятся «по справедливости»
Представьте, что у вас есть огромный склад с товарами (это ваша база данных). Если всё свалить в одну кучу, искать нужное будет долго и неудобно. Решение? Разделить склад на несколько зон (шардов), чтобы быстрее находить данные. И каждую из зон перенести в географически удобные локации (чем-то напоминает фордовскую децентрализацию), ведь речь о методе шардирования, а не партиционирования.
Но как решить, что в какую зону класть?
Вот тут на помощь приходит хэш-шардирование — метод, который распределяет данные по шардам с помощью хэша, алгоритма, который преобразует входные данные произвольной длины (называемые "ключом" или "сообщением") в выходные данные фиксированной длины (называемые "хэшем" или "хэш-кодом").
Ключ и хэш-функция: как распределить заказы
Ключ — атрибут, который используется для определения шарда, в котором будут храниться данные. Например:
ID клиента (если заказы распределяются по пользователям);
Номер заказа (если важно равномерное распределение).
Выбор ключа критичен! Если взять дату заказа, все заказы на «Черную пятницу» попадут в один шард, и он «захлебнется».
Хэш-функция — это алгоритм, который превращает ключ в число (хэш). Хорошая хэш-функция:
✔ Всегда выдаёт одно и то же число для одного ключа (иначе заказы Клиента №5 будут разбросаны по разным шардам);
✔ Распределяет ключи равномерно (чтобы не получилось, что 90% заказов попадают в один шард);
✔ Работает быстро (иначе система будет тормозить на каждом запросе).
Как данные попадают в нужный шард?
Допустим, у нас 4 шарда (Шард 0, Шард 1, Шард 2, Шард 3).
Берём ключ (например, user_id = 123);
Пропускаем его через хэш-функцию → получаем число (например, 347);
Делим это число на количество шардов и берем остаток:
347 : 4 = 3 → значит, данные попадут в Шард 3.
Теперь при запросе заказов пользователя 123 система сразу знает, где их искать!
Кто всем этим управляет?
В системе есть два главных героя:
Шарды — это отдельные «склады» (серверы, базы данных или разделы), где хранятся данные.
Координатор (Router) — это «диспетчер», который решает, куда отправить запрос. Когда приходит новый заказ, он:
считает хэш от ключа;
определяет шард;
отправляет данные туда.
Координатор может быть отдельным сервисом или частью приложения.
Плюсы и минусы: когда хэш-шардирование — отличный выбор?
Подойдет, если важны:
✅ Масштабируемость — можно добавлять новые шарды, когда данных становится больше;
✅ Равномерная нагрузка — если хэш-функция хорошая, данные распределяются без «перекосов»;
✅ Параллельная работа — запросы к разным шардам выполняются одновременно.
Может принести с собой:
❗️ Проблемы с изменением числа шардов — если добавить новый шард, придётся пересчитывать хэши и перемещать данные (это сложно!);
❗️ «Горячие точки» — если ключи плохие (например, 80% заказов от топовых клиентов), один шард будет перегружен;
❗️ Сложные запросы — если нужно собрать данные из нескольких шардов, придётся писать дополнительную логику.
Где используют?
Базы данных (SQL и NoSQL) — чтобы распределять данные между серверами;
Кэши (например, Memcached) — для хранения ключей на разных узлах;
Очереди сообщений (например, Kafka) — чтобы партиции не перегружались.
Вывод: когда выбирать хэш-шардирование?
✅ Подходит, если:
Нужно равномерное распределение данных;
Запросы чаще всего идут по одному ключу (например, «показать заказы пользователя X»);
Вы готовы к сложностям при масштабировании.
❗️ Не подходит, если:
Часто требуются аналитические запросы по всем данным (например, «сколько заказов за месяц»);
Ключи плохо распределены (например, 70% действий делают 10% пользователей).
Хэш-шардирование — как разделение пиццы на равные куски: если сделать правильно, всем достанется поровну. Но если кто-то захочет добавки, придётся перекраивать всю пиццу заново. Такой вот аттракцион!

2. Диапазонное шардирование: когда данные живут «по соседству»
Представьте библиотеку, где книги расставлены не по алфавиту, а по годам издания:
1900–1950 → первый стеллаж;
1951–2000 → второй стеллаж;
2001–2024 → третий стеллаж.
Это и есть диапазонное шардирование – данные распределяются не «в случайном порядке» (как в хэш-шардировании), а логическими блоками. Разберём, как это работает и когда полезно.
Ключ и диапазоны: как делим данные?
Главное условие: ключ должен быть упорядочиваемым (можно сравнить: больше/меньше). Примеры:
Дата (заказы по месяцам);
ID пользователя (если они выдаются последовательно);
Буквенный код (A–F, G–M и т.д.).
Диапазоны задаются вручную или автоматически. Например:
Шард 1: заказы с ID 1–1000
Шард 2: заказы с ID 1001–2000
Шард 3: заказы с ID 2001–3000
Если новый заказ имеет ID 1500 → он попадёт в Шард 2.
Как система находит нужный шард?
Здесь нет хэш-функций — только таблица маршрутизации, которая хранит правила:
Диапазон 1–1000 → Шард 1
Диапазон 1001–2000 → Шард 2
...
Координатор (роутер) проверяет ключ и отправляет запрос в нужный шард. Всё как в почтовом отделении, где письма сортируют по индексам!
Плюсы и минусы: когда выбирать?
Подойдет, если важны:
✅ Быстрые запросы по диапазону — например, «показать заказы за январь 2024» (данные лежат в одном шарде);
✅ Локальность данных — связанные записи (например, заказы одного клиента) хранятся рядом;
✅ Простота — легче реализовать, чем хэш-шардирование с consistent hashing.
Может принести с собой:
❗️ «Горячие точки» — если 90% заказов приходятся на январь, один шард будет перегружен;
❗️ Сложное масштабирование — добавление нового шарда требует перераспределения данных;
❗️ Зависимость от ключа — плохой выбор ключа (например, «дата рождения») может испортить распределение.
Как бороться с неравномерной нагрузкой?
Предварительное разделение — если знаете, что данные будут кластеризованы (например, праздничные заказы), заранее разбейте «горячий» диапазон на несколько шардов;
Динамическое деление — автоматически дробить перегруженные шарды (как в MongoDB);
Составные ключи — например, «дата + регион», чтобы равномернее распределить нагрузку.
Где используют?
Временные ряды (логи по дням/месяцам);
Биллинг-системы (транзакции по ID пользователя);
Аналитические базы данных (запросы по диапазону дат).
Вывод: когда подходит диапазонное шардирование?
✅ Выбирайте, если:
Часто выполняются запросы в стиле «показать данные от X до Y»;
Ключ имеет естественную упорядоченность (даты, последовательные ID);
Нужна простота реализации.
❗️ Избегайте, если:
Данные распределены неравномерно (например, 80% активности в одном месяце);
Часто меняется количество шардов.
Диапазонное шардирование — как книжные полки в библиотеке: если знать, что ищешь, находишь быстро. Но если все хотят одну и ту же книгу, то образуется очередь. 📖

P.S. Для «горячих» данных лучше комбинировать с другими методами (например, хэш-шардированием внутри диапазона).
3. Геошардирование: когда данные живут «по соседству». Буквально.
Представьте, что вы ищете ближайшую кофейню в приложении. Как система понимает, какие заведения показать? Всё просто — данные о местах хранятся не в одной куче, а разделены по географическим зонам. В этом и заключается основной принцип геошардирования.

Ключ и зоны: как делим мир, Пинки?
Ключ — это координаты (широта/долгота) или географический объект: город, район или даже произвольная фигура на карте.
Методы разделения:
Прямоугольные зоны — как разрезать карту на квадраты (просто, но неточно);
Геохеши — кодируем координаты в строку (например, u4pruy — это центр Осло). Чем длиннее хэш, тем точнее зона;
Границы городов/стран — данные группируются по административному делению;
Иерархия — сначала страны, потом регионы, затем города (как почтовые индексы).
Пример:
Шард 1: Нью-Йорк (40.7°N, 74.0°W)
Шард 2: Париж (48.8°N, 2.3°E)
Шард 3: Токио (35.6°N, 139.6°E)
Запрос с координатами Эйфелевой башни попадает в Шард 2.
Как система находит нужный шард?
Здесь работает пространственный индекс — специальная структура данных, которая быстро определяет, куда отправить запрос. Популярные варианты:
R-дерево — группирует объекты в «виртуальные прямоугольники»;
Квадродерево — рекурсивно делит карту на четверти;
Геохеш-индекс — ищет зону по строковому коду.
Координатор использует этот индекс, как навигатор: получил координаты → проверил индекс → направил запрос в нужный шард.
Плюсы и минусы: когда выбирать?
Подойдет, если важны:
✅ Молниеносные геозапросы — например, «кафе в радиусе 1 км» (данные уже лежат в одном шарде);
✅ Локальность данных — рестораны одного района хранятся вместе;
✅ Георепликация — можно разместить шарды ближе к пользователям (европейские данные — в Париже, азиатские — в Сингапуре);
Может принести с собой:
❗️ «Перекос данных» — в Москве миллион мест, а в Антарктиде — три (один шард перегружен, другие пустуют);
❗️ Граничные запросы — если пользователь стоит на границе двух шардов, система должна опрашивать оба;
❗️Динамические границы — если город расширяется, придется перераспределять данные.
Как бороться с проблемами?
Адаптивные зоны — автоматически дробить «густонаселенные» шарды (например, делить Нью-Йорк на Манхэттен, Бруклин и т.д.);
Геохеши + иерархия — сначала страна (первые 4 символа геохеша), потом город (еще 2 символа);
Репликация горячих точек — скопировать данные популярных мест в соседние шарды.
Где используют?
Картографические сервисы (Google Maps, Яндекс.Карты);
Такси и доставка (Uber, Bolt);
Соцсети (Instagram с геометками, Foursquare);
Игры с дополненной реальностью (Pokémon Go).
Вывод: когда подходит геошардирование?
✅ Выбирайте, если:
Данные привязаны к местоположению (чекины, заказы, датчики IoT);
Критичны быстрые геозапросы («показать всё рядом»);
Пользователи распределены по миру (и нужно уменьшить задержки).
❗️ Избегайте, если:
Данные распределены неравномерно (например, 90% активности в 3 городах);
Часто меняются границы зон (например, стартап, который ежедневно добавляет новые регионы).
Геошардирование — как раскладка товаров в супермаркете: молоко рядом с молоком, вино рядом с вином. Но если на районе все любят мороженое — очередь будет в одном холодильнике.
P.S. Для глобальных сервисов часто комбинируют геошардирование с репликацией — так данные становятся ближе к пользователям.
Итак, во второй части мы познакомились с тремя базовыми способами шардирования: по диапазону, по хэшу и по географическим зонам. Разобрались, как они работают, где помогают, а где могут устроить весёлую жизнь разработчикам, поддержке, аналитикам, CTO, гендиру... В общем, штука серьезная и подход должен быть соответствующий :)
Надо понимать, как данные живут, растут, какую нагрузку испытывают сервера и !с какой столкнутся в будущем! (да-да, несите кофейную гущу, будем гадать).
В следующей, заключительной части цикла мы продолжим тему и разберём более специфические стратегии шардирования, гибридные подходы и инструменты, которые могут существенно облегчить жизнь при работе с распределёнными базами данных.
А пока расскажите, применяете ли Вы принципы шардинга в своих системах? Что пробовали, что подошло, а что не очень? Буду рад обсудить ваши кейсы в комментах!