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

После переноса данных на несколько серверов запросы не обязательно становятся быстрее: один шард может получать большую часть записей, а запрос к нескольким шардам — ждать самый медленный из них. На примере PostgreSQL 16 разберём, что обычно ограничивает систему первым, какие метрики смотреть до масштабирования и где шардирование добавляет больше проблем, чем снимает.
Шардирование — это не просто несколько баз
В PostgreSQL 16 есть секционирование таблиц: данные можно разделить на части внутри одной базы и одного экземпляра сервера. Это помогает управлять большими таблицами и отсеивать ненужные секции при запросе, но само по себе не распределяет данные по разным серверам. Для такого распределения нужна отдельная маршрутизация — например, в приложении или в специализированном распределённом решении.
Дальше речь пойдёт о прикладном шардировании: приложение выбирает базу по ключу, например по идентификатору клиента, и направляет туда чтение или запись. Это добавляет ещё один уровень, за который кто-то должен отвечать: поддерживать карту размещения данных, переживать сбои и не отправлять запросы не туда.
Шард — отдельная часть набора данных, хранящаяся на самостоятельном узле или экземпляре базы. Ключ шардирования — значение, по которому приложение решает, где искать запись. Хвостовая задержка — время ответа для медленной части запросов, обычно оцениваемое по p95 или p99: например, p99 показывает границу, быстрее которой завершаются 99% запросов.
Что ломается первым под нагрузкой
1. Равномерность распределения
Суммарная ёмкость кластера не спасает, если один шард перегружен, а остальные простаивают. Такое происходит, когда ключ распределяет данные неравномерно или некоторые значения встречаются гораздо чаще других. Например, шардирование по идентификатору арендатора может перекосить нагрузку, если один крупный клиент создаёт намного больше событий, чем остальные.
Проблема становится заметна не только по общему CPU. Сравнивайте между шардами запросы в секунду, объём записей и чтений, задержки диска, число активных соединений, блокировки и p95/p99. Если на одном узле очередь запросов растёт быстрее, чем на соседних, сначала выясните причину перекоса. Добавление ещё одного сервера без изменения маршрутизации может ничего не дать.
2. Запросы, которые затрагивают несколько шардов
Запрос по известному ключу можно направить сразу в нужную базу. Но отчёт за день по всем клиентам, поиск без ключа или объединение данных нескольких клиентов могут потребовать обращений к нескольким шардам. Тогда система выполняет несколько запросов и сводит результаты вместе. При параллельном выполнении ответ обычно ждёт самый медленный запрос плюс время на координацию; при последовательном задержки могут складываться.
Такой запрос способен стать новым пределом производительности даже при свободных ресурсах на большинстве узлов. Чем больше шардов он опрашивает, тем больше соединений и результатов нужно обработать. Смотрите не только на среднее время ответа, но и на p95/p99, число затронутых шардов и размер данных, которые координатор передаёт и объединяет.
3. Записи сразу в несколько мест
Операция, которая раньше меняла связанные строки в одной базе, после разделения данных может затронуть разные шарды. Без специальной координации нельзя считать, что все изменения либо применятся, либо откатятся как одна неделимая транзакция. Один узел может принять запись, а другой — ответить ошибкой или стать недоступным. Приложению понадобится явно определённый порядок действий: например, повтор операции, компенсация уже выполненного шага или отдельный процесс сверки.
Не переносите на кластерные границы прежние гарантии одной базы автоматически. Проверьте, где создаются уникальные идентификаторы, как обеспечиваются ограничения между связанными сущностями и что происходит при тайм-ауте после фактически принятой записи. Повтор запроса без защиты от дублей может создать повторное событие или платёж.
Шардирование ускоряет запрос только тогда, когда система знает, к какому узлу обратиться. Запрос, который приходится разослать всем, превращает каждый новый шард в дополнительную работу.
Как понять, пора ли разделять базу
Рост нагрузки сам по себе не доказывает, что нужен новый шард. Сначала убедитесь, что ограничение действительно в базе, а не в медленном запросе, нехватке индексов, конкурирующих блокировках, диске или слишком большом числе соединений. Сравните поведение приложения и базы в одни и те же периоды: иначе можно принять за причину совпавший симптом.
- Зафиксируйте исходные p95 и p99 для ключевых запросов, долю ошибок и число запросов в секунду.
- Снимите нагрузку отдельно по каждому узлу: CPU, ожидание диска, соединения, блокировки, объём чтения и записи.
- Разделите запросы на адресные — с ключом шардирования — и широкие: отчёты, поиск и операции без такого ключа.
- Оцените перекос распределения на реальных данных, включая крупнейших клиентов и самые частые ключи.
- Проверьте план на случай отказа узла и переноса части данных: шардирование добавит эти операции к обычному обслуживанию.
Сравнивайте результаты до и после на одинаковом профиле запросов и данных. Универсального числа одновременных пользователей или размера базы, после которого пора шардировать, нет: предел зависит от запросов, оборудования и допустимой задержки. Если проблема исчезает после исправления тяжёлого запроса или настройки индексов, шардирование могло бы лишь усложнить систему.
Цена разных способов разделить данные
| Подход | Что выигрываете | Чем платите |
|---|---|---|
| Одна база PostgreSQL 16 | Простая маршрутизация и транзакции в рамках одного экземпляра | Предел одного сервера; сначала нужно проверить запросы, индексы и ресурсы |
| Секционирование в PostgreSQL 16 | Разделение большой таблицы на секции и возможность не читать ненужные части | Данные остаются в одном экземпляре; это не распределение нагрузки между серверами |
| Шардирование в приложении | Контроль над размещением и возможность разносить нагрузку по узлам | Нужны маршрутизация, управление переносом данных и обработка межшардовых операций |
Таблица не заменяет нагрузочный тест. Например, секционирование помогает только тогда, когда структура таблицы и запросы позволяют отсеивать лишние секции. Прикладное шардирование имеет смысл, если значительная часть критичных запросов содержит ключ, по которому можно выбрать один шард, а команда готова поддерживать распределённую систему.
Границы решения: когда шардирование не спасёт
Если запросы регулярно обходят все узлы, растёт не только нагрузка на базы, но и объём работы по сбору результатов. Если один ключ создаёт непропорциональный поток записей, выбранный способ распределения оставит горячий шард. Если приложению нужны частые атомарные изменения на разных узлах, цена координации может оказаться выше выигрыша от распределения.
Отдельный риск — перенос уже размещённых данных. При изменении правил маршрутизации приложение должно понимать, где находится каждая запись во время перехода, а перенос не должен перегрузить рабочие узлы. До запуска определите, как проверяется полнота копирования, как переключается чтение и что делать, если процесс остановился посередине. Конкретный порядок зависит от реализации; универсальной безопасной процедуры для всех систем нет.
Оговорка по версии: здесь речь о возможностях PostgreSQL 16. В других версиях, а также при использовании расширений или внешних систем распределённой базы детали могут отличаться. Перед проектированием сверяйте поведение с документацией именно того решения, которое запускаете.
Что делать дальше
Снимите профиль нагрузки по запросам и узлам до изменения архитектуры. Найдите самые медленные запросы, измерьте перекос между предполагаемыми шардами и отдельно посчитайте долю операций, которые требуют данных из нескольких мест. Затем проверьте сценарии отказа и переноса данных на тестовом окружении. Если после теста адресные запросы укладываются в требования, а цена межшардовых операций понятна, можно оценивать шардирование как конкретный компромисс, а не как автоматическое лечение роста нагрузки.
Логотип и фирменный стиль: Три концепции разного характера, палитра с обоснованием, проверка на читаемость в малом размере и в один цвет.
Спросить за 60 ₽Источники: PostgreSQL 16: секционирование таблиц, PostgreSQL 16: мониторинг активности базы данных
Частые вопросы
Как понять, что PostgreSQL пора шардировать?
Что чаще всего ломается первым после добавления шардов?
Можно ли считать секционирование в PostgreSQL 16 шардированием?
Как поступить, если мой PostgreSQL другой версии?
Что делать, если после шардирования запрос стал медленнее?
Какие подводные камни особенно опасны в проде?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.