Шардирование
Шардирование (от англ. sharding) — это метод горизонтального масштабирования базы данных, при котором большая таблица (или набор данных) физически разбивается на несколько независимых, более мелких частей, называемых шардами (shards). Каждый шард представляет собой отдельную логическую или физическую единицу хранения (например, отдельную базу данных, запущенную на отдельном сервере), содержит подмножество строк исходной таблицы и обрабатывается независимо от других шардов. Цель шардирования — распределить нагрузку по чтению и записи, а также объем хранимых данных между несколькими узлами кластера, преодолевая ограничения одной машины (CPU, RAM, дисковая подсистема).
История и предпосылки появления
Необходимость в шардировании возникла по мере роста объемов данных и требований к производительности веб-приложений и сервисов в конце 1990-х — начале 2000-х годов. Традиционные реляционные базы данных (СУБД), такие как Oracle, MySQL или PostgreSQL, хорошо масштабируются вертикально (апгрейд до более мощного сервера), но это имеет физические и экономические пределы. Вертикальное масштабирование не решает проблему географической распределённости и не позволяет парировать пиковые нагрузки гибко.
Пионерами в применении шардирования стали крупные интернет-компании, столкнувшиеся с миллионами пользователей: Google (концепция Bigtable, позже — Spanner), Amazon (DynamoDB), Facebook (продукт Meta, признанной экстремистской и запрещённой в РФ) (Apache Cassandra), Twitter, eBay. В частности, в 2004 году компания Flickr опубликовала опыт шардирования MySQL на свой страх и риск без готовых инструментов — это стало отправной точкой для популяризации подхода в сообществе разработчиков. Постепенно концепция шардирования легла в основу многих NoSQL-решений (MongoDB, Cassandra, HBase), а также встроенных механизмов масштабирования современных NewSQL-систем (Vitess, CockroachDB, Yandex ClickHouse, Greenplum).
В России шардирование активно применяется в высоконагруженных системах «Яндекса», VK, «Сбербанка», «Тинькофф Банка», а также при построении государственных информационных систем (ЕГАИС, ЕМИАС, ГИС ГМП) для обеспечения их доступности при пиковых нагрузках.
Классификация и виды шардирования
Шардирование классифицируется по способу распределения данных между шардами и по способу маршрутизации запросов.
По способу распределения данных
- Диапазонное шардирование (Range Sharding). Данные распределяются на основе диапазона значений ключа шардирования (например, идентификатора пользователя от 1 до 10 000 — шард A, от 10 001 до 20 000 — шард B). Простая реализация, но может приводить к дисбалансу нагрузки (один шард перегревается, другой простаивает) при неравномерном распределении ключей или популярности диапазонов.
- Хеш-шардирование (Hash Sharding). Ключ шардирования хешируется (обычно с помощью хеш-функции, например, MD5, SHA-1 или модификации модуля). Хеш-значение определяет номер шарда. Обеспечивает равномерное распределение данных, если хеш-функция хорошо сбалансирована. Недостаток: сложность перешардирования при добавлении или удалении узлов — требуется пересчёт всех хешей и перемещение данных (решение — консистентное хеширование, используемое в DynamoDB и Cassandra).
- Географическое (Geo-Sharding). Данные распределяются по шардам, расположенным в разных географических регионах, для минимизации задержек для локальных пользователей. Часто применяется в CDN-системах, глобальных социальных сетях (например, Facebook размещает данные пользователей в шардах, расположенных в регионе проживания пользователя, с учётом требований законодательства).
- Функциональное (Functional Sharding). Данные разбиваются не по строкам, а по функциональным признакам (например, таблица «Пользователи» разделена на шард «Профили» и шард «Комментарии»). На практике это ближе к денормализации и часто сочетается с горизонтальным шардированием.
По способу маршрутизации запросов
- Прозрачное шардирование (Transparent / Application-Level). Маршрутизация запросов осуществляется на уровне приложения: код содержит логику определения, к какому шарду обратиться (через карту шардов или хеш-функцию). Требует от разработчика глубокого понимания топологии кластера. Пример: реализация в ранних версиях Ruby on Rails (ActiveRecord Sharding).
- Посредническое (Proxy-Based / Middleware). Запросы проходят через слой-посредник, который сам определяет нужный шард. К приложению такой слой является единой точкой доступа. Пример: Vitess (шлюз для MySQL), ProxySQL, Apache ShardingSphere (для JDBC).
- Управляемое СУБД (Native / Database-Level). Механизм шардирования встроен в саму СУБД: приложению не нужно знать о шардах, СУБД сама распределяет данные и маршрутизирует запросы. Пример: MongoDB (через config servers), Cassandra (через partitioner), CockroachDB, Greenplum (через segment hosts), YDB (распределённая СУБД «Яндекса»).
Устройство и архитектура
Ключевыми компонентами реализации шардирования являются:
- Узел шарда (Shard Node) — физический сервер или виртуальная машина, на которой размещён один шард (чаще всего — экземпляр СУБД). В кластере может быть от 2 до нескольких сотен узлов.
- Ключ шардирования (Shard Key) — столбец или набор столбцов таблицы, на основе которого определяется принадлежность строки к конкретному шарду. Выбор правильного ключа — критически важный этап; при неудачном выборе возникает дисбаланс нагрузки или невозможность эффективного выполнения JOIN.
- Каталог шардов (Configuration Server / Lookup Service) — служба, хранящая метаданные о том, какие шарды существуют, какие ключи им соответствуют, какой текущий статус (онлайн/офлайн). В MongoDB эту роль выполняют узлы настроек (config servers), в Cassandra — Gossip-протокол.
- Маршрутизатор (Router / Proxy) — компонент, принимающий запрос от приложения и перенаправляющий его на нужный шард. В прокси-архитектурах (Vitess, ProxySQL) знает текущую карту шардов и может выполнять запросы параллельно (fan-out).
- Координатор запросов (Query Coordinator) — на распределённых системах (Cassandra, Greenplum) компонент, собирающий результаты от нескольких шардов и выдающий единый ответ приложению (поддерживает операции SORT, GROUP BY, LIMIT).
Архитектура шардирования может быть симметричной (все шарды используются для одного набора данных, например, при диапазонном шардировании) или асимметричной (шарды разного размера, существуют «горячие» и «холодные» партиции).
Применение
Шардирование применяется в высоконагруженных системах, где требования к производительности и доступности превышают возможности одной машины:
- Социальные сети и мессенджеры — хранение миллионов профилей, постов, сообщений (VK, Telegram, WhatsApp).
- Электронная коммерция — каталоги товаров с миллионами позиций, заказы, корзины, истории просмотров (Ozon, Wildberries).
- Системы управления контентом (CMS) и платформы для публикации — хранение статей, комментариев (Wikipedia, Medium).
- Банковские системы — операционная день-в-день обработка транзакций (CORE-системы), хранение выписок, кредитных историй.
- IoT и мониторинг — запись показаний датчиков с миллионов устройств в реальном времени (платформы «Ростелекома», системы «Умный город»).
- Системы машинного обучения и аналитики — хранение и обработка больших датасетов (Data Lake, Data Warehouse на базе ClickHouse, Vertica, Greenplum).
- Государственные информационные системы — портал «Госуслуги», ГИС ЖКХ, система «Меркурий» (Россельхознадзор) — периодически выдерживают пиковые нагрузки при подаче заявлений.
Примеры
- MongoDB. Поддерживает автоматическое шардирование с помощью набора узлов конфигурации (config servers) и маршрутизатора mongos. Ключ шардирования определяется администратором; распределение — диапазонное или хеш-шардирование (через хеш-индекс). Данные внутри шарда могут дополнительно реплицироваться для отказоустойчивости.
- Apache Cassandra. Каждая таблица (column family) имеет свой partitioner, который хеширует первичный ключ и распределяет данные по кольцу узлов (ring topology). Шардирование в Cassandra — встроенное, не требует ручного управления. Добавление и удаление узлов автоматически перераспределяет токены.
- Vitess. Платформа для горизонтального масштабирования MySQL, разработанная YouTube. Предоставляет прокси-слой с поддержкой автоматического ребалансирования (resharding), резервным копированием и онлайн-миграцией схемы данных.
- PostgreSQL (с Citus). Расширение Citus Data, приобретённое Microsoft, превращает PostgreSQL в распределённую базу данных с возможностью шардирования таблиц по ключу. Широко используется в SaaS-приложениях.
- ClickHouse. Предназначен для аналитических запросов — данные могут шардироваться по ключам для распараллеливания сканирования по нескольким узлам (distributed tables).
Критика и ограничения
Несмотря на эффективность, шардирование вносит существенную сложность:
- Сложность JOIN. Выполнение операций объединения данных из разных шардов требует дополнительных затрат (сбор данных на координаторе, сетевые задержки). На практике разработчики вынуждены денормализовывать данные или использовать вложенные документы.
- Перешардирование (Resharding). Изменение количества шардов при росте данных или при неравномерной нагрузке — крайне сложная операция, часто требующая перегрузки данных (миграции). Некоторые системы (Cassandra, Mongoose) поддерживают онлайн-перешардирование, но оно временно снижает производительность.
- Горячие точки (Hot Spots). Если ключ шардирования выбран неудачно, на один шард может приходиться непропорционально большая нагрузка (например, таблица логов по одному источнику). Решается хеш-шардированием или изменением ключа.
- Глобальные индексы. Если первичный шардированный индекс ускоряет запросы по ключу, то поиск по другим столбцам требует просмотра всех шардов (фан-аут), что резко замедляет работу. Для решения строят вторичные индексы с дублированием.
- Транзакции. Распределённые транзакции (ACID) между шардами — дорогие, slow, и их поддержка в большинстве СУБД может быть неполной (не все системы гарантируют изоляцию). В high-load системах часто используют компенсирующие транзакции (Saga) или отказываются от сильной согласованности.
- Управление сложностью. Необходимость в специализированных DevOps-инженерах, знающих архитектуру распределённых систем и конкретную реализацию шардирования.
Альтернативы
Шардирование — не единственный способ масштабирования. Альтернативы:
- Вертикальное масштабирование (Scale-up) — замена на более мощный сервер. Просто, но имеет физический предел.
- Репликация — создание копий (реплик) одной базы данных на нескольких серверах (master-slave, multi-master) для балансировки чтения. Репликация не решает проблему хранения объёмов данных, превышающих диск одного сервера.
- Партиционирование (Partitioning) — разбиение таблицы в пределах одной базы данных на логические отрезки (партиции) по диапазону значений столбца. Это более простой, чем шардирование, метод, но данные остаются на одной машине.
- Распределённые файловые системы (HDFS, MinIO) — хранение данных как файлов, а не таблиц — используют MapReduce для обработки, что даёт иное распределение нагрузки, но неприменимо для оперативных запросов с низкой задержкой.
Источники
- Kleppmann, Martin. «Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems». O’Reilly Media, 2017. (Глава 6: Partitioning)
- MongoDB, Inc. «Sharding — MongoDB Manual». [Онлайн-документация].
- Apache Cassandra Project. «Partitioners». [Официальная документация].
- Vitess. «Sharding and Resharding Overview». [Официальная документация].
- Spooner, Adam. «A Brief History of Sharding». Flickr Code Blog (2004) (архив).
- DB-Engines. «Sharding vs Replication vs Partitioning: Key Differences». [Обзорная статья].
- «Шардирование в ClickHouse». Яндекс.Документация, 2023.
- «Проблемы масштабирования высоконагруженных систем: опыт VK». Доклад на HighLoad++, 2019.
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →