База дали: чеклист подготовки инфраструктуры к масштабированию
Запрос «база дали» обычно ведёт к разговору о больших данных и распределённом хранении. В технической спецификации такого термина нет. Вероятнее всего, речь о data lake или о базе данных, которую нужно подготовить к росту нагрузки.

Это разные задачи: озеро данных хранит разнородные наборы для последующей обработки, а рабочая СУБД обслуживает запросы приложения с заданными требованиями к задержке и доступности.
Масштабирование начинается не с покупки более крупного сервера. Сначала нужно понять, что именно ограничивает систему: CPU, память, диск, сеть, блокировки в базе, неэффективный запрос или архитектурная зависимость от одного узла. Иначе дополнительная мощность увеличит счёт, но оставит прежнее узкое место. Для проектирования хранилищ данных и интеграции данных в enterprise нужна спецификация нагрузки, понятная схема отказов и проверяемый план изменений.
1. Опишите нагрузку до выбора архитектуры
Слово «рост» слишком расплывчато для инженерного решения. Рост числа пользователей, потока событий и объёма архива создаёт разную нагрузку. Увеличение числа чтений может упереться в пропускную способность базы. Рост записей способен усилить конкуренцию за ресурсы и увеличить задержки. Увеличение объёма данных влияет на индексы, резервное копирование и длительность обслуживания.
Перед масштабированием зафиксируйте исходные условия:
- какие операции преобладают: чтение, запись, обновление, пакетная загрузка;
- как меняются RPS и QPS в обычном режиме и в пиковые периоды;
- сколько данных поступает, сколько хранится и как быстро растёт объём;
- какие запросы критичны для пользовательского пути;
- какие задержки допустимы для синхронной операции, а какие можно вынести в фоновую обработку;
- что должно происходить при отказе узла или временной потере связи между компонентами.
RPS — число входящих запросов к сервису в секунду. QPS — число запросов, которые обрабатывает база или другой компонент за секунду. Эти показатели связаны, но не взаимозаменяемы: один запрос приложения может породить несколько запросов к базе, а часть операций может завершаться в кэше или очереди.
Универсального порога RPS или QPS, после которого пора шардировать, нет. Он зависит от схемы данных, характера запросов, оборудования и требований к задержке. Поэтому бенчмарк должен воспроизводить реальный профиль нагрузки, а не только создавать большое число однотипных запросов.
Масштабировать нужно измеряемое ограничение. Пока его нет в метриках, архитектурное решение будет догадкой.
2. Выберите момент перехода от вертикального роста к горизонтальному
Вертикальное масштабирование означает увеличение ресурсов одного узла: процессоров, памяти или производительности хранения. Это часто самый короткий путь, если приложение и база ещё имеют запас по архитектуре, а узкое место локализовано. Но такой путь не отменяет единую точку отказа: если критичный компонент остаётся на одном узле, его отказ способен остановить систему.
Горизонтальное масштабирование добавляет узлы и распределяет между ними нагрузку или данные. Оно требует согласовать маршрутизацию, репликацию, поведение при отказах и эксплуатационные процедуры. Сам факт наличия нескольких серверов ещё не создаёт распределённую архитектуру. Если приложение продолжает обращаться к одному перегруженному узлу, кластер существует только на схеме.
Практический порядок действий:
1. Снимите профиль нагрузки и определите компонент, который первым достигает ограничения.
2. Проверьте запросы, индексы и конфигурацию. Не переносите на кластер проблему, которую можно устранить в запросе или модели данных.
3. Оцените, даст ли вертикальное увеличение ресурсов измеримый запас. Зафиксируйте, какой ресурс должен измениться и по какой метрике это будет видно.
4. Определите требования к отказоустойчивости. Если допустим простой при отказе единственного узла, это осознанное ограничение. Если простой недопустим, нужна схема с резервированием и проверенным переключением.
5. Проектируйте горизонтальное расширение под конкретную нагрузку: чтение, запись, хранение или обработку данных.
Для распределённых систем цена изменения выше, чем цена добавления узла. Появляются сетевые сбои, задержки межузлового взаимодействия, операции синхронизации и сценарии частичного отказа. Эти свойства должны попасть в спецификацию до деплоя, а не обнаружиться в инциденте.
3. Разделяйте задачи репликации, партиционирования и шардирования
Термины часто смешивают, хотя они решают разные задачи. Репликация создаёт копии данных. Партиционирование делит таблицу на части. Шардирование распределяет данные по отдельным узлам или серверам. Эти механики можно сочетать, но одна не заменяет другую.
| Механика | Что меняется | Для чего применяют | Что усложняется |
|---|---|---|---|
| Репликация | Создаются копии основного набора данных | Масштабирование чтения, наличие копий для отказоустойчивой схемы | Согласованность копий, переключение, задержка доставки изменений |
| Партиционирование | Таблица делится на логические части | Работа с большими таблицами и ограничение объёма данных, затрагиваемого операцией | Выбор ключа и правил обслуживания частей |
| Шардирование | Строки или другие части данных распределяются по узлам | Распределение хранения и нагрузки между серверами | Маршрутизация запросов, перебалансировка и операции между шардами |
Репликация полезна, когда система перегружена чтениями. Копии могут обслуживать часть запросов, но их наличие не гарантирует, что все чтения увидят последнее изменение. Если приложению критична актуальность только что записанных данных, чтение с реплики требует отдельного решения: например, часть запросов должна идти к основному узлу или учитывать задержку синхронизации.
Партиционирование помогает организовать таблицы и сократить работу с данными, которые не относятся к конкретному запросу. Здесь ключевой вопрос — как запросы фильтруют данные. Если типовые операции не позволяют системе отсеивать ненужные части, само деление таблицы не даст ожидаемого эффекта.
Шардирование распределяет строки по узлам. Оно способно снять ограничение одного сервера, но добавляет обязательный архитектурный выбор: по какому ключу распределять данные. Неудачный ключ создаёт горячий шард, на который приходится непропорционально много запросов. Перенос данных между шардами также требует процедур, наблюдаемости и проверки корректности.
Перед внедрением выберите механизм по фактической проблеме. Репликация для чтения не решает перегрузку записи на основном узле. Партиционирование таблицы не заменяет распределение нагрузки между серверами. Шардирование без стратегии ключей может лишь разделить исходную проблему на несколько узлов и добавить сетевую сложность.
Для архитектуры распределённых данных отдельно зафиксируйте, какие операции должны быть атомарными, какие запросы затрагивают несколько частей данных и как восстанавливается сервис после отказа узла. Ответы влияют на модель данных и интерфейсы приложения. Их нельзя надёжно заменить настройкой кластера после запуска.
4. Измеряйте хвост задержки, а не только среднее
Среднее время отклика сглаживает редкие, но болезненные задержки. Например, большинство запросов может выполняться быстро, а небольшая доля — ожидать блокировку, медленный диск или перегруженный узел. Среднее значение не показывает, насколько медленно обслуживается эта часть запросов.
Для пользовательского опыта используйте перцентили:
- P95 — граница задержки, в которую укладываются 95% запросов;
- P99 — граница для 99% запросов.
Оставшиеся запросы могут выполняться дольше. Именно этот хвост часто виден пользователям во время пиков и становится причиной таймаутов в цепочках сервисов. В распределённой архитектуре задержка одного запроса может складываться из нескольких сетевых вызовов и операций в базах. Поэтому метрику нужно смотреть на уровне сервиса и отдельных зависимостей.
Для каждого критичного маршрута сопоставляйте P95 и P99 с RPS, ошибками, таймаутами и ресурсными показателями. Если P99 растёт одновременно с числом запросов, проверьте насыщение ресурсов и очереди. Если перцентиль ухудшается при стабильной нагрузке, возможны проблемы в отдельных запросах, блокировках или неравномерном распределении данных. Одно значение без контекста не локализует причину.
Мониторинг должен сохранять разрезы по операциям и зависимостям. Общая метрика по всему приложению способна скрыть медленный endpoint за большим числом быстрых запросов. Аналогично, усреднение по всем узлам маскирует перегруженный шард. Системе нужны метрики, по которым можно перейти от пользовательского симптома к конкретному компоненту.
Порог тревоги задают исходя из требований продукта и базового профиля. Копировать чужие значения P95 или P99 бессмысленно: разные операции имеют разный бюджет задержки. После изменения архитектуры бенчмарк и нагрузочный тест должны показывать, что целевой перцентиль сохраняется при ожидаемом профиле запросов.
5. Управляйте инфраструктурой через IaC
Когда число окружений и узлов растёт, ручные настройки начинают расходиться. Один сервер получает исправление, другой остаётся со старой конфигурацией. После инцидента трудно определить, какие изменения были внесены и как вернуть систему в предыдущее состояние.
Infrastructure as Code описывает конфигурацию инфраструктуры в виде кода. Это даёт видимость развёрнутых ресурсов и позволяет управлять изменениями через привычный процесс: коммит, проверка, деплой. При ошибке появляется возможность откатить изменение к известному состоянию, если сам процесс и состояние инфраструктуры организованы соответствующим образом.
Минимальная рабочая практика включает:
1. Хранение конфигураций в системе контроля версий. Изменение инфраструктуры должно иметь автора и историю.
2. Разделение параметров по окружениям. Тестовая конфигурация не должна случайно подменять производственную.
3. Проверку изменений до применения. Ошибка в шаблоне или параметре способна затронуть несколько компонентов сразу.
4. Фиксацию секретов отдельно от обычных конфигурационных данных. Пароли и ключи не должны попадать в репозиторий в открытом виде.
5. План восстановления. Откат кода не всегда автоматически возвращает состояние базы или внешнего ресурса; процедуру нужно проверять на практике.
IaC не гарантирует корректную архитектуру и не устраняет уязвимость в приложении. Он делает конфигурацию обозримой и воспроизводимой. Ошибочное описание инфраструктуры, применённое автоматически, тоже масштабирует ошибку. Поэтому изменения требуют ревью и контроля результата после деплоя.
При подготовке инфраструктуры к масштабированию полезно разделить код, который создаёт ресурсы, и код, который задаёт конфигурацию приложения. Это упрощает диагностику: можно отдельно выяснить, изменился ли состав узлов, сетевые правила, параметры СУБД или поведение самого сервиса.
6. Учтите специфику векторных хранилищ
Векторная база добавляет к обычным запросам поиск по близости в многомерном пространстве. Для оценки такой системы недостаточно спросить, сколько векторов она хранит. Нужны как минимум три параметра: задержка, пропускная способность и качество поиска. Последнее часто выражают через recall, то есть долю релевантных результатов, найденных алгоритмом.
В одном из приведённых бенчмарков Qdrant на наборе из 100 млн векторов показал 4200 QPS и P99 в 12 мс при recall@10 = 0,991. Эти цифры относятся к конкретному бенчмарку и его условиям. Их нельзя трактовать как гарантированную производительность для произвольной схемы, оборудования или профиля запросов. При сравнении результатов должны совпадать размер и размерность векторов, фильтры, параметры поиска и требования к качеству выдачи.
Для pgvector в фактуре указаны ограничения: до 2000 измерений для индексируемых векторов и до 16000 для хранения. Это влияет на выбор модели и способа поиска. Если вектор превышает предел индексирования, возможность хранить его сама по себе не означает, что выбранный индекс применим. До внедрения проверьте размерность эмбеддингов, тип индекса и фактический запрос.
Нагрузочный тест векторного хранилища должен включать реальные фильтры и характерные запросы. Поиск без фильтра и поиск с ограничением по атрибутам могут вести себя по-разному. Также измеряйте recall вместе с P95/P99: ускорение поиска с потерей качества может оказаться неприемлемым для прикладного сценария.
Если векторный поиск становится частью критичного пути приложения, определите поведение при недоступности хранилища. Нужно ли возвращать ошибку, использовать резервный механизм, ставить операцию в очередь или показывать результат без семантического поиска. Это решение относится к архитектуре сервиса, а не только к настройке базы.
Перед масштабированием зафиксируйте ограничения
Рабочая последовательность для подготовки системы выглядит так: описать профиль нагрузки, локализовать узкое место, выбрать механизм расширения, определить метрики приёмки и проверить сценарии отказа. Для данных отдельно укажите правила репликации, партиционирования или шардирования. Для деплоя опишите конфигурацию в IaC и включите её изменения в контролируемый процесс.
Перед запуском проверьте, что команда может ответить на несколько вопросов:
- Какая метрика подтверждает, что система упёрлась в ограничение?
- Как изменятся P95 и P99 после внедрения?
- Что произойдёт при отказе основного узла, реплики или шарда?
- Как данные распределяются и где вероятна неравномерная нагрузка?
- Как восстановить конфигурацию после неудачного деплоя?
- Какими тестами подтверждены пропускная способность и качество поиска?
Если ответов нет, инфраструктура ещё не готова к масштабированию. Добавление серверов в такой ситуации увеличит число компонентов, но не даст управляемой системы. Сначала нужна спецификация, затем изменение архитектуры и только потом расширение ресурсов.