Начать проект

Обсудим проект?

Нажимая на кнопку, вы даете согласие на обработку персональных данных и соглашаетесь с политикой конфиденциальности.

Отправлено!

Спасибо за заявку, мы свяжемся с вами в ближайшее время!

Проектирование высоконагруженных систем: как посчитать нагрузку и что ломается первым

Высоконагруженная система — балансировка, кеш, очереди и реплики базы данных

Разговор про highload обычно начинается после первого падения в пик: реклама сработала, пришло в десять раз больше людей, чем обычно, а сайт лёг на самом интересном месте. Мы в Code Pilots делаем веб-приложения и порталы с высокими нагрузками — от магазина на 500 тысяч позиций до приложения фестиваля с сотней тысяч одновременных пользователей, и почти всегда узкое место оказывается не там, где его ищут.

Если совсем коротко. Высокая нагрузка — не абстрактный статус, а конкретные цифры: пиковые запросы в секунду, объём данных и допустимое время ответа. Считать их надо до разработки, потому что архитектура зависит именно от них.

Первым ломается почти всегда база данных, а не «сервер». Отдельно стоит проверить контракт с клиентами: если API спроектирован без пагинации и лимитов, лишнюю нагрузку создаёт сам клиент. Помогают четыре вещи: убрать состояние из сервисов, добавить кеш, вынести тяжёлое в очереди и научить систему деградировать вместо падения. И до релиза всё это нужно проверить нагрузочным тестом — иначе вы узнаете правду в пик.

Что считается высокой нагрузкой

Единого порога нет, и любой, кто называет точное число, продаёт услугу. Практический ориентир по уровням:

Уровень Порядок нагрузки Что обычно достаточно Что уже нужно
Обычный До сотни запросов в секунду, база в десятки гигабайт Один сервер приложения, одна база, базовое кеширование Нормальные индексы и мониторинг
Средний Сотни запросов в секунду, заметные суточные пики Несколько инстансов за балансировщиком, кеш, реплика для чтения Stateless-сервисы, вынос тяжёлых операций в фон
Высокий Тысячи запросов в секунду, терабайты данных Горизонтальное масштабирование, кеш-кластер, очереди, разделение чтения и записи Продуманная схема данных, лимиты, деградация
Экстремальный Десятки тысяч запросов в секунду, резкие всплески Шардирование, распределённые кеши, отдельные контуры под нагрузку Постоянные нагрузочные прогоны, дежурство, план на отказ

Важнее уровня — форма нагрузки. Ровные тысячи запросов в секунду проектировать проще, чем всплеск в сорок раз на пять минут: во втором случае система должна успеть подняться или мягко ограничить поток. Именно всплески дают самые дорогие падения — распродажи, эфиры, старт продаж билетов.

Полезно сразу развести нагрузку и объём. Миллион товаров в каталоге и миллион пользователей в минуту — разные задачи: первая про схему данных и поиск, вторая про горизонтальное масштабирование. Как устроена серверная часть в целом, разобрано в материале про бэкенд.

Как посчитать свою нагрузку до разработки

Считается это на салфетке, и без такого расчёта архитектуру обсуждать бессмысленно.

Шаг 1 — активные пользователи. Сколько людей пользуется сервисом в сутки. Для нового продукта берётся план по маркетингу, а не мечта.

Шаг 2 — действия на пользователя. Сколько экранов и запросов делает один человек за сессию. Отдельно считаются запросы к API от мобильного приложения: их обычно в разы больше, чем кажется.

Шаг 3 — коэффициент пика. Суточные запросы делятся не на 86 400 секунд, а на реальное окно активности. Для сервиса с вечерним пиком коэффициент к среднему — от трёх до десяти; для распродажи или эфира — десятки.

Шаг 4 — целевое время ответа. 200 миллисекунд на API-запрос и 2 секунды на страницу — разные бюджеты по архитектуре и деньгам.

Шаг 5 — данные. Объём базы через год, размер медиа, срок хранения истории. Часто именно рост данных, а не запросы, требует шардирования.

Итог расчёта — четыре числа: пиковые запросы в секунду, целевой отклик, объём данных на горизонте года и допустимое время недоступности. С ними уже можно спорить об архитектуре предметно, а не «давайте сделаем масштабируемо».

Как посчитать нагрузку: пользователи, действия, коэффициент пика, целевой отклик

Нагрузка — не среднее за сутки, а пик в самую неудачную минуту вашего года.

Что ломается первым

Порядок почти всегда один и тот же, и это не про мощность сервера.

База данных. Тяжёлые запросы без индексов, блокировки при массовых обновлениях, счётчики в одной строке, полнотекстовый поиск по таблице на десятки миллионов записей.

Запросы в цикле. Классический N+1: страница дёргает базу по разу на каждый элемент списка. На тестовых данных незаметно, на реальном каталоге — сотни запросов на одну страницу.

Медиа и файлы. Картинки без кеша и без внешней раздачи упираются в приложение; генерация превью на лету в пик добивает процессор.

Синхронные вызовы наружу. Оплата, доставка, склад, СМС: внешний сервис отвечает медленно, ваши потоки заняты ожиданием, очередь запросов растёт, всё стоит.

Состояние в памяти процесса. Сессии и корзины, лежащие в одном инстансе, не дают добавить второй сервер: пользователя перекидывает и он теряет данные.

Логи и метрики. Неожиданный, но частый пункт: синхронная запись подробных логов в пик тормозит само приложение.

Найти узкое место без данных нельзя, поэтому начинается всё не с переписывания, а с профилирования. В проектах, которые мы подхватываем, аудит кода и архитектуры обычно показывает, что до 80% просадки дают несколько запросов и отсутствие кеша — их правят за дни, а не за месяцы.

Найдём узкое место до распродажи

Аудит кода и архитектуры плюс нагрузочный прогон покажут, где система сложится, — пока это стоит дней работы, а не упущенной выручки.

Обсудить проект

Паттерны, которые реально работают

Паттерн Что даёт Когда вводить Цена решения
Stateless-сервисы Возможность добавить инстансы простым копированием Сразу, это дешёво Сессии и файлы выносятся во внешние хранилища
Кеш Снимает основную часть однотипных чтений При первых просадках на чтении Появляется вопрос инвалидации
Реплики для чтения Разгружают основную базу Когда чтений в разы больше записей Задержка репликации, часть данных «отстаёт»
Очереди Быстрый ответ пользователю, тяжёлое в фоне Как только появляются длинные операции Асинхронность усложняет логику и отладку
Идемпотентность Повтор запроса не создаёт второй заказ Сразу для платежей и внешних обменов Нужны ключи операций и хранение результатов
Разделение чтения и записи Отдельные модели под разные нагрузки Когда одна схема не устраивает и тех и других Сложнее код, нужна синхронизация
Шардирование Горизонтальный рост базы Когда данные и запись не влезают в один узел Самый дорогой шаг: меняется схема и логика
Автомасштабирование Инстансы поднимаются под нагрузку При заметных пиках Холодный старт: успеть подняться до пика

Порядок ввода важен не меньше самого списка: сверху вниз он идёт от дешёвого к дорогому. Ошибка «сразу шардируем» встречается чаще, чем ошибка «забыли про кеш».

Паттерны highload по возрастанию цены: stateless, кеш, реплики, очереди, шардирование

База данных: где заканчивается «докупить сервер»

Вертикальное масштабирование — самое простое и до определённого предела самое разумное решение: больше памяти и быстрее диски дают кратный рост без переписывания кода. Предел наступает, когда упирается запись — её нельзя размножить репликами.

Дальше три шага, по возрастанию цены:

Реплики для чтения. Отчёты, каталог, поиск уходят на реплики, основная база остаётся для записи. Учтите задержку: только что созданный заказ может не появиться в отчёте мгновенно, и это нужно предусмотреть в интерфейсе.

Разделение по доменам. Логи, аналитика, поиск и очереди переносятся из основной базы в специализированные хранилища. Часто этого достаточно, чтобы отложить шардирование на годы.

Шардирование. Данные делятся на независимые части, у каждой свой мастер. Это меняет и схему, и код: появляется ключ шардирования, кросс-шардовые запросы становятся дорогими, а транзакции между шардами — отдельной задачей.

Практическое правило: слой абстракции над доступом к данным стоит заложить сразу, даже если шардирование не планируется. Тогда переход не потребует переписывания половины приложения. О том, как выбор технологий влияет на такие решения, — в материале про стек технологий.

Кеш: где он помогает и где стреляет в ногу

Кеш — самый быстрый способ снять нагрузку и самый быстрый способ получить новый класс проблем.

Что кешируют. Результаты тяжёлых запросов, карточки товаров, справочники, ответы внешних сервисов, готовые фрагменты страниц.

Главная проблема — инвалидация. Данные изменились, а в кеше лежит старая версия. Стратегия выбирается осознанно: срок жизни, сброс по событию, версионирование ключей. Универсального ответа нет, но «кешируем на час и надеемся» — не стратегия.

Холодный старт. После перезапуска или сброса кеш пуст, и вся нагрузка падает на базу — ровно в тот момент, когда она меньше всего этого ждёт. Лечится прогревом заранее.

Лавина запросов. Ключ истёк, и сто параллельных запросов одновременно бегут в базу за одним и тем же. Решается блокировкой на пересчёт или обновлением до истечения срока.

Что нельзя кешировать бездумно. Остатки товара, цены с персональными условиями, права доступа. Здесь ошибка кеша стоит дороже, чем экономия на запросах.

Очереди и асинхронность

Очередь — это способ ответить пользователю сразу, а тяжёлую работу сделать потом. Отчёты, письма, экспорт, обработка изображений, обмен с внешними системами, пересчёт рекомендаций — всё это не должно происходить в момент нажатия кнопки.

Что даёт очередь под нагрузкой: сглаживает пики, потому что задачи копятся и обрабатываются с постоянной скоростью; изолирует сбои, потому что упавший внешний сервис не роняет ваш интерфейс; позволяет масштабировать обработчики отдельно от веб-части.

Чем платите: усложняется логика (пользователь не видит результат сразу), нужны понятные статусы, обработка повторов и мёртвых сообщений, мониторинг длины очереди. Асинхронность — это не «поставили RabbitMQ», а проектирование поведения продукта.

Из практики: у B2B-дистрибьютора алкоголя мы держим обмен с хранилищем данных на RabbitMQ и Go с отликом меньше полусекунды, а у «Радиоэлементов» с 500 тысячами позиций конструктор парсеров прайс-листов обрабатывает файл поставщика за 30–120 секунд вместо часов ручной работы — это тоже фоновая обработка, просто в промышленном масштабе. Техническая сторона обменов между системами разобрана в материале про интеграционную шину.

Деградация вместо падения

Самая недооценённая часть проектирования. Любая система имеет предел, и вопрос не в том, наступит ли он, а в том, как система себя поведёт.

Лимиты на вход. Ограничение частоты запросов на пользователя и на общий поток. Лучше вежливо притормозить часть трафика, чем упасть для всех.

Отключение тяжёлых функций. В пик можно выключить персональные рекомендации, отчёты, экспорт, тяжёлые фильтры. Продукт беднеет на час, но работает.

Предохранитель на внешние вызовы. Если сервис доставки не отвечает, запросы к нему прекращаются на время, а пользователю показывается понятное сообщение вместо бесконечного ожидания.

Очередь ожидания. На старте продаж билетов честная очередь с номером и оценкой времени лучше, чем сайт, который не открывается.

Заранее подготовленные заглушки. Статическая версия каталога, кешированная главная, режим «только чтение». Их надо не придумывать в момент аварии, а проверить заранее.

Хорошая система под перегрузом отдаёт меньше, а не падает целиком.

Нагрузочное тестирование

Без теста все рассуждения об архитектуре — гипотезы. Нагрузочное тестирование отвечает на три вопроса: где предел, что ломается первым, как система восстанавливается.

Профиль нагрузки. Тест повторяет реальное поведение: доля чтений и записей, распределение по разделам, длина сессии. Ровный поток запросов на главную ничего не проверяет.

Метрики. Смотреть надо не среднее время ответа, а перцентили: p95 и p99. Среднее прячет ровно тех пользователей, из-за которых вы получите жалобы.

Виды прогонов. Постепенный рост до предела, длительный тест на стабильность, резкий всплеск, тест восстановления после отказа компонента.

Инструменты. В российских проектах чаще всего встречаются четыре:

Инструмент Чем хорош Когда брать
Yandex.Tank Заточен под высокие нагрузки, хорошо стреляет по HTTP, детальные отчёты Когда нужен жёсткий обстрел и много запросов с одной машины
k6 Сценарии на JavaScript, удобно встраивается в CI Когда тесты пишет команда разработки и они живут вместе с кодом
JMeter Зрелый инструмент с графическим интерфейсом и множеством протоколов Когда тестируют не только HTTP и нужны готовые плагины
Gatling Точные отчёты и хорошая работа с длительными сценариями Когда важна детальная картина по перцентилям в динамике

Выбор зависит не от рейтингов, а от того, что ваша команда сможет поддерживать: тест, который никто не запускает после релиза, бесполезен.

Где тестировать. На стенде, максимально похожем на прод по конфигурации, с реалистичным объёмом данных. Тест на пустой базе даёт красивые цифры и никакой информации.

Дальше начинается цикл: нашли предел, поправили узкое место, повторили. Первые два-три прохода обычно дают кратный рост без изменения архитектуры — за счёт индексов, запросов и кеша.

Соберём систему, которая держит пик

Stateless-сервисы, кеш, очереди и деградация вместо падения — на проектах с сотней тысяч одновременных пользователей.

Получить консультацию

Наблюдаемость и дежурство

Система, за которой никто не смотрит, о своих проблемах сообщит через клиентов. Минимальный набор, который закладывается в проект, а не «потом»:

  • Метрики: запросы в секунду, время ответа по перцентилям, ошибки, загрузка ресурсов, длина очередей, попадания в кеш.
  • Логи с идентификатором запроса, чтобы проследить путь одной операции через все сервисы.
  • Трассировка — где именно в цепочке потерялись секунды.
  • Алерты по симптомам, а не по всему — растёт доля ошибок, деградирует p99, копится очередь. Алерт, который срабатывает каждый день, перестают читать.
  • Дежурство и порядок эскалации: кто смотрит, что делает первым, кого поднимает.
  • Цели по доступности (SLO) — договорённость о том, какой уровень сбоев считается нормой. Без неё спор «работает или нет» бесконечен.

У себя мы держим мониторинг обменов со статусами и алертами в Telegram: для интеграционных контуров это первый признак проблемы, который приходит раньше жалоб.

Когда highload вам не нужен

Обратная сторона темы, о которой подрядчики говорят редко. Преждевременное усложнение обходится дорого и замедляет разработку.

Признаки, что вам пока хватит простой архитектуры: нагрузка в пределах сотни запросов в секунду, база в десятки гигабайт, пики предсказуемые и не в разы, а на десятки процентов. В этой ситуации микросервисы, шардирование и кластер кеша дадут не устойчивость, а сложность в эксплуатации и счёт за инфраструктуру.

Что действительно стоит сделать сразу и стоит недорого: убрать состояние из сервисов, завести мониторинг, закрыть очевидные узкие места в запросах, спроектировать схему данных с учётом роста и заложить слой абстракции над доступом к данным. Этого достаточно, чтобы вырасти в десять раз без переписывания.

Мы говорим об этом прямо на первом звонке: если задача не требует highload-архитектуры, продавать её мы не будем.

Сколько стоит и из чего складывается

Стоимость highload-проекта складывается из четырёх частей: проектирование архитектуры и схемы данных, разработка, инфраструктура с запасом мощности и нагрузочное тестирование с последующей оптимизацией. Последние две части в первых сметах обычно отсутствуют, а потом дают неприятный сюрприз.

Отдельно считается запас: система, рассчитанная ровно на ожидаемый пик, ляжет на первом же превышении прогноза. Разумный подход — держать кратный запас по мощности на короткие всплески и уметь докупать ресурсы быстро.

Ориентиры по нашим работам: сложные и высоконагруженные системы начинаются от 5 млн ₽, аудит кода и архитектуры существующей системы — от 200 до 600 тыс. ₽, отдельная интеграция — от 150 тыс. до 1,5 млн ₽. Точная сумма зависит от профиля нагрузки, требований к отклику и состояния текущего кода: оценка проекта бесплатная — опишите задачу.

Сильный аргумент в защиту бюджета — стоимость простоя. Час недоступности в пик распродажи считается в упущенной выручке и в оттоке; на этом фоне запас по мощности и нагрузочный прогон выглядят дешёвой страховкой. Порядок суммы для такой защиты удобно прикинуть в бесплатном калькуляторе оценки.

Ошибки

Проектировать по среднему. Средняя нагрузка за сутки не говорит ничего: система живёт или умирает в пиковую минуту.

Начинать с микросервисов. Распределённая система на старте даёт распределённые проблемы: сетевые задержки, согласованность данных, отладка через пять сервисов.

Кешировать всё подряд. Без стратегии инвалидации кеш начинает отдавать неверные остатки и цены — и это дороже медленных запросов.

Забыть про идемпотентность. Повторный запрос из-за таймаута создаёт второй заказ и второй платёж; всплывает это в самый неудачный момент.

Не тестировать под нагрузкой. Единственный способ узнать предел — прогон. Все остальные способы называются надеждой.

Оставить систему без наблюдаемости. Без метрик и трассировки инцидент разбирают по описаниям пользователей, а не по данным.

Не предусмотреть деградацию. Система, которая умеет только работать полностью или не работать вовсе, обязательно выберет второе в неподходящий момент.

С чего начать

Три шага, которые дают предметный разговор. Первое — посчитать профиль нагрузки: пиковые запросы в секунду, целевое время ответа, объём данных на год вперёд, допустимое время недоступности. Второе — снять метрики с текущей системы, если она есть: время ответа по перцентилям, самые тяжёлые запросы, попадания в кеш, длину очередей. Третье — определить критичный сценарий, который нельзя терять ни при какой нагрузке: оформление заказа, оплата, регистрация на событие.

С этими данными видно, нужна ли вам новая архитектура или достаточно оптимизации существующей. По нашему опыту второе встречается чаще, и это хорошая новость для бюджета.

С чего начать: посчитать профиль нагрузки, снять метрики, определить критичный сценарий

Обсудим вашу нагрузку?

Посчитаем профиль, посмотрим текущие метрики и оценим объём работ. Оценка бесплатная.

Обсудить проект

Часто задаваемые вопросы

Единого порога нет. Ориентир: до сотни запросов в секунду хватает одного сервера с кешем; сотни требуют нескольких инстансов за балансировщиком и реплики для чтения; тысячи — горизонтального масштабирования и очередей; десятки тысяч — шардирования. Важнее уровня форма нагрузки: всплеск в сорок раз на пять минут проектируется иначе, чем ровный поток.

Почти всегда база данных: тяжёлые запросы без индексов, блокировки, счётчики в одной строке. Дальше — запросы в цикле (N+1), медиа без внешней раздачи, синхронные вызовы внешних сервисов, сессии в памяти процесса и, неожиданно, подробное логирование. Искать узкое место нужно профилированием, а не переписыванием: часто несколько запросов и отсутствие кеша дают основную часть просадки.

Нет, это разные вещи. Монолит с stateless-сервисами, кешем и очередями держит очень высокую нагрузку. Микросервисы решают организационную задачу — независимые команды и релизы — и добавляют сетевые задержки, сложность отладки и проблемы согласованности данных. На старте они чаще вредят, чем помогают.

Нагрузочным тестом на стенде, похожем на прод, с реалистичным объёмом данных и профилем поведения пользователей. Смотреть надо p95 и p99, а не среднее время ответа. Прогоны нужны разные: постепенный рост до предела, длительный на стабильность, резкий всплеск и восстановление после отказа компонента. Плюс заранее проверенный режим деградации: что вы отключите, если поток превысит расчёт.

У нас сложные и высоконагруженные системы начинаются от 5 млн ₽, аудит кода и архитектуры — от 200 до 600 тыс. ₽, интеграция — от 150 тыс. до 1,5 млн ₽. Кроме разработки в смету входят проектирование схемы данных, инфраструктура с запасом и нагрузочное тестирование. Точная цифра — по профилю нагрузки, оценка бесплатная.

Разработка с Code Pilots

Code Pilots — студия заказной разработки полного цикла, и высокие нагрузки вместе со сложными интеграциями — наш профиль, а не побочная компетенция.

Для VK Fest мы собрали приложение фестиваля с сотней тысяч одновременных пользователей: MVP за два месяца командой из пяти человек и первое место в Google Play. «Радиоэлементы» с 500 тысячами позиций работают с нами больше десяти лет, PetShop — тоже: highload-магазин, а мобильное приложение на готовой API-платформе вышло за две недели.

Что мы делаем в таких проектах: считаем профиль нагрузки, проектируем схему данных и архитектуру, закрываем узкие места, строим обмены на очередях, настраиваем наблюдаемость и прогоняем нагрузочные тесты до релиза, а не после. DevOps внутри проекта у нас включён всегда.

Границы обозначим честно: серверный парк и железо мы не аудируем и не поставляем — работаем с кодом, архитектурой и инфраструктурой в облаке. Если задача не требует highload-решений, скажем об этом сразу. Обсудить проект →

Обсудим проект?

Заполните форму или напишите нам
на airmail@code-pilots.ru
Нажимая на кнопку, вы даете согласие на обработку персональных данных и соглашаетесь с политикой конфиденциальности.

Спасибо!

Спасибо за сообщение, мы свяжемся
с вами в ближайшее время!
success