Базы данных

Шардинг: горизонтальное масштабирование записи

В 2010 году у Twitter была проблема: 400 миллионов твитов в день не помещались на один MySQL сервер. Инженеры создали Gizzard - систему шардинга MySQL. Сейчас YouTube обрабатывает 500 часов видео в минуту через Vitess - тот же MySQL, но с шардингом на 100,000+ серверов.

  • **Shopify**: Vitess для MySQL шардинга - 1 млн+ магазинов, пики в Black Friday без downtime
  • **Instagram**: 10,000+ PostgreSQL шардов для хранения данных 2 млрд пользователей
  • **Uber**: 1000+ PostgreSQL шардов для trip history, геолокаций, pricing данных

Зачем нужен шардинг

Вертикальное масштабирование (добавить CPU/RAM) имеет предел. Самый мощный сервер AWS (x2iedn.32xlarge) стоит $26/час и имеет 4TB RAM. Когда данные не помещаются - нужен шардинг: разбить данные на несколько серверов (shards). Каждый shard = независимая БД, хранит подмножество данных.

Шардинг - последнее средство оптимизации. Сначала: индексы, caching, read replicas, вертикальное масштабирование. Шардинг добавляет огромную сложность: нет JOIN между шардами, нет глобальных транзакций, resharding болезненен.

Когда шардинг необходим?

Hash vs Range шардинг

Hash шардинг: shard = hash(key) % N. Равномерное распределение данных, нет hot shards. Минус: range queries требуют обращения ко всем шардам (scatter-gather). Range шардинг: shard по диапазону значений (A-M на shard1, N-Z на shard2). Range queries эффективны, но возможны hot shards (все новые записи с timestamp на последний шард).

ПараметрHash ShardingRange Sharding
Распределение данныхРавномерноеМожет быть неравномерным
Range queriesScatter-gather (все шарды)Эффективно (один шард)
Hot shardsМаловероятныРиск при монотонном key
Используется вCassandra, MongoDBHBase, DynamoDB (при range key)

Consistent hashing - улучшение hash шардинга: при добавлении нового шарда перемещается только 1/N данных, а не полный resharding. Используется в Cassandra, Amazon DynamoDB, Memcached. Узлы образуют кольцо, данные переходят только к ближайшему новому соседу.

Система хранит временные ряды с timestamp как ключом. Какой шардинг выбрать?

Проектирование Shard Key

Shard key - самое важное архитектурное решение при шардинге. Изменить его потом = полный resharding = часы даунтайма или сложная online migration. Критерии хорошего shard key: высокая cardinality (много уникальных значений), равномерное распределение, соответствует access patterns (связанные данные на одном шарде).

Instagram shard approach: logical_shard_id = user_id % 2000, physical_shard = mapping[logical_shard_id]. Двухуровневый маппинг: 2000 логических шардов на любое количество физических. Добавить физический сервер = переместить часть логических шардов.

Таблица заказов. Какой shard key выбрать если нужны: "все заказы пользователя" и "все заказы за период"?

Resharding

Resharding - перераспределение данных между шардами при добавлении новых или изменении shard key. Наивный подход: остановить систему, перенести данные, запустить. Это недопустимо для production. Online resharding требует: двойная запись в старый и новый шард, миграция данных в фоне, проверка консистентности, переключение чтения.

Vitess (used by Shopify, GitHub, YouTube) управляет MySQL шардингом: online resharding, query routing, connection pooling. PlanetScale (hosted Vitess) позволяет менять схему без locks, resharding без даунтайма.

При добавлении нового шарда с hash шардингом (user_id % 100 -> % 101) что происходит?

Cross-Shard запросы

Cross-shard query - запрос к данным на нескольких шардах. Пример: "найти топ-10 активных пользователей" - нужно опросить все шарды (scatter), объединить результаты (gather), отсортировать. При 100 шардах - 100 параллельных запросов + merge в application layer.

Распределённые транзакции через шарды (2PC - Two-Phase Commit) возможны, но крайне медленны из-за blocking protocol. Shopify избегает cross-shard транзакций через data modeling: связанные данные на одном шарде (customer + orders на customer_shard).

Шардинг автоматически ускоряет все запросы

Шардинг ускоряет запросы к конкретному шарду (при правильном shard key). Cross-shard queries медленнее, чем в нешардированной БД при небольших данных.

Шардинг добавляет overhead: network hop, scatter-gather, нет JOIN. Выигрыш только при данных, превышающих возможности одного сервера.

Шардинг по user_id. Как эффективно получить "заказы за последние 24 часа по всем пользователям"?

Ключевые идеи

  • **Shard key**: самое важное решение - высокая cardinality, равномерность, соответствие access patterns; изменить после = пересоздать всё
  • **Hash vs Range**: hash = равномерность, range queries по всем шардам; range = эффективные range queries, риск hot shards
  • **Cross-shard queries**: scatter-gather, pre-aggregation, или data modeling избегающий cross-shard joins

Связанные темы

Шардинг строится поверх репликации и требует понимания партиционирования:

  • Партиционирование — Партиционирование - шардинг внутри одного сервера; схожие принципы выбора ключа
  • Consistent Hashing — Consistent hashing минимизирует resharding при добавлении узлов
  • Репликация — Каждый шард обычно имеет собственные replicas для HA

Вопросы для размышления

  • Как Instagram выбирала shard key при 10,000+ шардах PostgreSQL? Какие trade-offs они сделали?
  • Система e-commerce: таблицы users, orders, products. По какому принципу шардировать каждую?
  • Consistent hashing добавляет 1/N данных при новом шарде. Почему это лучше чем 100% при обычном hash % N?

Связанные уроки

  • dist-14-sharding
Шардинг: горизонтальное масштабирование записи

0

1

Войти