Вопрос с собеседования · Highload

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

MiddleШардирование и распределение данных
Ещё спрашивают так:
  • Чем шардирование по диапазону отличается от шардирования по хешу?
  • Что делать с запросами, которые затрагивают несколько шардов?
  • Когда пора шардировать базу?
Коротко

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

  • По диапазону — удобны диапазонные запросы, но новые ключи бьют в один шард (время, автоинкремент)
  • По хешу — равномерно, но диапазонный запрос идёт во все шарды
  • По справочнику (directory) — гибко, но нужен сервис-каталог

А ещё Шардировать последним: сначала индексы, кэш, реплики для чтения, вертикальное масштабирование, архивирование

Попробуйте сами

Consistent hashing и виртуальные узлы

Подробно

Зачем. Одна машина упирается в объём данных, запись или память под рабочий набор. Реплики масштабируют только чтение. Шардирование масштабирует и запись, и объём — ценой сложности.

Стратегии:

  • по диапазону ключа: A–F на шард 1, G–M на шард 2; или по датам. Плюсы — диапазонные запросы и сортировка внутри шарда, простое разделение растущего шарда пополам (так делают HBase, Spanner, CockroachDB, MongoDB с range). Минус — горячий хвост: монотонные ключи (время, автоинкремент) пишутся в последний шард;
  • по хешу ключа: hash(user_id) mod N или consistent hashing. Равномерно, монотонные ключи рассеиваются. Минус — диапазонный запрос обходит все шарды (scatter-gather), смена N перемещает данные;
  • по справочнику — таблица «ключ или диапазон → шард». Можно переносить отдельных крупных клиентов, но каталог становится критичным сервисом (обычно кэшируется);
  • географическое — данные пользователя в его регионе (задержка, законы о локализации данных).

Как выбирать ключ — от запросов, а не от данных:

  • большинство запросов должно содержать ключ и попадать в один шард: для мессенджера — chat_id, для магазина — tenant_id или user_id;
  • связанные данные — в один шард (заказы пользователя рядом с ним), чтобы транзакции и JOIN оставались локальными;
  • высокая кардинальность и равномерность — не country и не status;
  • учесть «китов»: один клиент на 30% нагрузки не поделится хеш-функцией.

Что становится сложным:

  • запросы без ключа — scatter-gather по всем шардам, медленно и с хвостами; решают вторичными индексами в отдельном хранилище (поисковый индекс, денормализованная проекция);
  • транзакции между шардами — саги, outbox, двухфазный коммит или перепроектирование, чтобы их не было;
  • уникальность и глобальные id — генераторы вроде Snowflake;
  • JOIN между шардами — денормализация, справочники копируются на все шарды;
  • решардинг — перенос данных без простоя.

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

Пример

Сервис заказов: 20 млн пользователей, 95% запросов — «заказы пользователя».
Ключ — user_id, хеш, 16 шардов: заказы и позиции пользователя в одном шарде.
«Все заказы за день» для аналитики — не из шардов, а из потока изменений в ClickHouse.
«Заказ по номеру» — номер содержит номер шарда (или user_id), чтобы не обходить все.

Что хотят услышать

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

Частые ошибки

  • Шардировать по автоинкременту или времени по диапазону — все записи в один шард.
  • Выбирать ключ, не посмотрев на основные запросы.

Проверьте себя

Один верный вариант. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✗Шардирование по времени распределяет новые записи равномерно
  • ✓Частые запросы — в один шард, нагрузка — равномерна
  • ✗Шардирование по хешу удобно для диапазонных запросов
  • ✗Ключ шардирования выбирают случайно

Что спросят дальше

Связанные вопросы

Партнёр платформы

Разбор собеседования с sotto

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

Разбор собеседования