Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Задачи

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

AI info

Карта сайта

Документы

Медиа

Назад
Вопрос про Postgres: sharding

Как выбирается ключ шардирования?

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

Короткий ответ

Ключ шардирования выбирают так, чтобы данные распределялись равномерно и запросы чаще попадали в один шард. Обычно берут поле с высокой уникальностью (например, user_id) и стабильной семантикой. Важно избегать ключей, которые создают “горячие” шарды, например дату или монотонно растущий идентификатор без хеширования. Также учитывают, как будут выполняться JOIN и выборки по основным фильтрам.

Длинный ответ

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

Что важно от ключа шардирования

Сначала формулируют требования к ключу, иначе шардирование быстро превращается в постоянную “борьбу с перекосами”.

1) Равномерное распределение данных

Ключ должен давать близкий к равномерному распределению:

  1. высокая кардинальность (много разных значений)

  2. отсутствие сильной корреляции с временем/нагрузкой

  3. отсутствие “топовых” значений, на которые приходится большинство операций

Пример плохого ключа:

  • created_at (все новые записи идут в один “хвост”)

  • country (несколько больших стран перегружают отдельные шарды)

2) Локальность запросов

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

  1. запросы по user_id → шардирование по user_id

  2. запросы по tenant_id (multi-tenant) → шардирование по tenant_id

Если запросы регулярно требуют данных “со всех шардов”, вы получите fan-out:

  • растет латентность

  • растут расходы на сеть

  • усложняется отказоустойчивость

3) Отсутствие hotspot

Hotspot — это шард, который постоянно “горячий” из-за перекоса в данных или трафике.

Типовые причины:

  1. монотонно растущий ключ без хеширования

  2. небольшое множество популярных значений

  3. “топовые” пользователи/тенанты, генерирующие основной трафик

Частая техника для борьбы:

  • использовать hash(user_id) вместо “сырого” user_id

  • или консистентное хеширование на уровне роутинга

4) Стабильность ключа

Ключ должен редко меняться. Если значение ключа меняется — запись нужно “перевезти” в другой шард, а это:

  1. дорогая операция

  2. требует согласованности

  3. усложняет транзакции и ссылки

Поэтому, например, email как ключ часто плох, а user_id — хорош.

5) Влияние на связи и транзакции

Шардирование меняет жизнь JOIN и транзакций.

Если у вас есть частые связи:

  • orders ↔ users

  • payments ↔ orders

то разумно выбирать ключ так, чтобы связанные сущности попадали в один шард. Например:

  • orders шардинг по user_id

  • payments шардинг по тому же user_id или по order_id, если order_id однозначно привязан к user_id и роутинг это знает

Типовые стратегии выбора

Шардирование по ID (user-centric)

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

  1. большинство запросов “вокруг пользователя”

  2. нужен хороший баланс

  3. удобна локальность

Пример роутинга:

shard = hash(user_id) % N

Шардирование по tenant_id (multi-tenant)

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

  1. система multi-tenant

  2. важна изоляция крупных клиентов

  3. возможны отдельные политики на тенанта

Минус: “крупный тенант” может перегреть один шард, тогда приходится делать “тенант внутри тенанта” или отдельные шарды для крупных.

Шардирование по времени (time-series)

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

  1. партиционирования внутри шарда

  2. аккуратной стратегии на “горячий хвост”

  3. возможного split горячих диапазонов

Практический мини-пример

Допустим, основной паттерн: “показать профиль и последние заказы пользователя”.

Тогда логично:

  1. users шардировать по user_id

  2. orders шардировать по user_id

  3. читать данные без fan-out

Пример (упрощенно):

GET /users/42
GET /users/42/orders?limit=20

Оба запроса идут в один и тот же шард.

Вывод

Ключ шардирования выбирают так, чтобы обеспечить баланс (без hotspot), локальность большинства запросов (минимум fan-out), стабильность (редко меняется) и разумную модель для связей/транзакций. На практике чаще всего выигрывает user_id или tenant_id с хешированием.

  • Аватар

    Golang Guru

    Maxim Lukyanov

    Guru – это эксперты YeaHub, которые помогают развивать комьюнити.

Уровень

  • Рейтинг:

    5

  • Сложность:

    8

Навыки

  • Postgres

    Postgres

Ключевые слова

#sharding

Подпишись на Golang Developer в телеграм

  • Аватар

    Golang Guru

    Maxim Lukyanov

    Guru – это эксперты YeaHub, которые помогают развивать комьюнити.