Как выбрать ключ и стратегию шардирования?
- Чем шардирование по диапазону отличается от шардирования по хешу?
- Что делать с запросами, которые затрагивают несколько шардов?
- Когда пора шардировать базу?
Шардирование делит данные между узлами по ключу шардирования. Ключ выбирают так, чтобы частые запросы шли в один шард, а нагрузка распределялась равномерно.
- По диапазону — удобны диапазонные запросы, но новые ключи бьют в один шард (время, автоинкремент)
- По хешу — равномерно, но диапазонный запрос идёт во все шарды
- По справочнику (directory) — гибко, но нужен сервис-каталог
А ещё Шардировать последним: сначала индексы, кэш, реплики для чтения, вертикальное масштабирование, архивирование
Подробно
Зачем. Одна машина упирается в объём данных, запись или память под рабочий набор. Реплики масштабируют только чтение. Шардирование масштабирует и запись, и объём — ценой сложности.
Стратегии:
- по диапазону ключа: 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 минут бесплатно.