Backpressure на собеседовании системного аналитика

Проверь себя · 1/3разбор после ответа
Вы хотите получить одну строку на пользователя с итоговой выручкой и заменили GROUP BY на оконную SUM(amount) OVER (PARTITION BY user_id). Почему результат содержит столько же строк, сколько и исходный набор?

Почему backpressure спрашивают

Backpressure — это классический вопрос системного дизайна для системного аналитика. Как только в задаче появляются слова «поток событий», «очередь», «интеграция сервисов» или «нагрузка» — интервьюер проверяет, понимаете ли вы, что происходит, когда одна часть системы производит данные быстрее, чем другая их успевает переваривать.

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

Эта статья закрывает базовые вопросы по теме: что такое backpressure, что случается без него, какие есть стратегии и как это описывать в требованиях к системе.

Что такое backpressure

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

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

В распределённых системах роль «трубы» играет буфер или очередь между сервисами, а роль «насоса» — сервис-производитель (API, брокер сообщений, поток событий). Без обратной связи производитель не знает, что потребитель захлёбывается, и продолжает слать данные в никуда.

Что происходит без backpressure

Если система не умеет тормозить производителя, есть только два плохих сценария.

Первый — неограниченная очередь. Буфер между сервисами растёт бесконечно, пока не съест всю память:

Быстрый производитель → 10 000 сообщений/сек → медленный потребитель (100/сек)
Очередь растёт без предела → OutOfMemory → падение сервиса

Второй — потеря данных. Если очереди нет или она переполнилась, лишние сообщения просто отбрасываются:

Нет буфера → входящие сообщения не помещаются → сообщения теряются

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

Стратегии обработки backpressure

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

  • Буферизация (buffer). Ставим ограниченную очередь. Пока в ней есть место, производитель работает свободно; как только буфер заполнился — включается обратное давление. Ключевое слово — «ограниченная»: неограниченный буфер не решает проблему, а лишь оттягивает падение по памяти.
  • Отбрасывание (drop). При переполнении часть сообщений выбрасывается — самые старые, самые новые или случайные. Подходит там, где важна свежесть, а не полнота: например, телеметрия или метрики, где потеря одного замера не критична.
  • Приостановка производителя (pause). Производитель блокируется и ждёт, пока очередь разгрузится. Гарантирует, что ничего не потеряется, но замедляет весь конвейер и может создать очередь уже на стороне производителя.
  • Троттлинг (throttle). Производителю жёстко ограничивают скорость (rate limiting) — например, не больше N запросов в секунду. Темп заранее подстроен под потребителя, всплески сглаживаются.
  • Сэмплирование (sample). Обрабатываем только часть потока, остальное игнорируем. Осмысленно для аналитики в реальном времени, где важна тенденция, а не каждое отдельное событие.
  • Сброс на диск (spillover). При переполнении памяти данные временно уходят на диск. Память не переполняется, но растёт задержка и нагрузка на диск.

На собесе важно не перечислить ярлыки, а связать выбор с требованиями. Для платежей и заказов терять сообщения нельзя — значит buffer + pause и никакого drop. Для потока кликов или логов допустимо drop или sample, зато нельзя жертвовать задержкой. Именно эту логику «критичность против задержки» интервьюер и хочет услышать.

Готовься к собесу аналитика как в Duolingo
10 минут в день — SQL, Python, A/B, метрики. 1700+ вопросов в Telegram
Открыть Карьерник в Telegram

Reactive Streams

Reactive Streams — стандарт для асинхронного backpressure. Он описывает, как производитель и потребитель договариваются о скорости без блокировок.

Суть спецификации в модели «спрос по запросу» (pull-based): потребитель сам запрашивает у производителя N элементов, производитель присылает не больше N, и цикл повторяется. Производитель физически не может завалить потребителя — тот забирает ровно столько, сколько готов обработать. Это противоположность наивному push-подходу, где источник шлёт всё подряд и надеется, что приёмник справится.

Спецификацию реализуют несколько библиотек:

  • Project Reactor — реактивный стек в экосистеме Java/Spring (типы Flux и Mono).
  • RxJava / RxJS — реактивные расширения для Java и JavaScript.
  • Akka Streams — потоковая обработка поверх акторной модели.
  • Kotlin Flow — встроенные корутины и холодные потоки в Kotlin.

Пример на Kotlin Flow, где backpressure задаётся оператором на уровне кода:

flow.buffer(100)         // ограниченный буфер на 100 элементов
    .conflate()          // отбрасывать промежуточные, оставлять только последнее
    .collect { ... }     // потребитель забирает элементы в своём темпе

Здесь buffer(100) даёт ограниченную очередь, а conflate() реализует стратегию drop-старых: если потребитель отстаёт, промежуточные значения схлопываются и остаётся самое свежее.

Backpressure в реальных системах

Системному аналитику полезно знать, что backpressure не только в реактивных библиотеках — он встроен во многие протоколы и брокеры:

  • TCP имеет встроенное обратное давление через скользящее окно (flow control): приёмник объявляет размер окна, и отправитель не шлёт больше, чем помещается.
  • Kafka реализует backpressure на стороне потребителя: consumer сам вызывает poll() и забирает столько, сколько успевает обработать, а offset коммитит после обработки. Продюсер при этом не давит напрямую на потребителя — данные копятся в топике до истечения retention.
  • gRPC-стриминг поддерживает backpressure на уровне HTTP/2-потоков: приёмник управляет окном, и отправитель приостанавливает передачу.

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

Частые ошибки

  • Предлагать неограниченную очередь. «Поставим буфер побольше» без слова про его предел — это отложенный OutOfMemory, а не backpressure. Очередь обязана быть ограниченной.
  • Молчать про потерю данных. Стратегия drop допустима, но её нельзя применять к платежам и заказам. Кандидат должен сам оговорить, где терять сообщения нельзя.
  • Путать backpressure с ретраями. Ретраи повторяют неудачные запросы, backpressure регулирует скорость успешных. При перегрузке агрессивные ретраи только усугубляют лавину.
  • Игнорировать компромисс задержка/полнота. Любая стратегия — это выбор между «ничего не терять» и «не расти по задержке». Ответ без явного компромисса выглядит неполным.
  • Считать, что backpressure решается только кодом. Часто он уже встроен в протокол (TCP, HTTP/2, Kafka). Не нужно изобретать то, что даёт транспорт.

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

FAQ

Чем backpressure отличается от rate limiting?

Rate limiting — это жёсткий потолок скорости, заданный заранее и не зависящий от состояния потребителя: «не больше 1000 запросов в секунду». Backpressure — динамическая обратная связь: производитель замедляется ровно настолько, насколько отстаёт потребитель прямо сейчас. Троттлинг можно считать одной из стратегий backpressure, но сам по себе rate limiting не знает, справляется приёмник или нет.

Что выбрать: буферизацию или отбрасывание?

Зависит от критичности данных. Если терять сообщения нельзя (платежи, заказы) — ограниченный буфер плюс приостановка производителя. Если важнее свежесть, а не полнота (метрики, телеметрия, клики) — drop или sample, чтобы не копить задержку. Ключевой вопрос интервьюеру: «что дороже — потерянное сообщение или выросшая задержка?».

Backpressure — это то же самое, что очередь?

Нет. Очередь — это буфер, а backpressure — механизм обратной связи, который срабатывает, когда буфер заполнился. Можно иметь очередь без backpressure (тогда она растёт до OutOfMemory) и backpressure без явной очереди (например, pull-модель в Reactive Streams, где потребитель просто запрашивает следующую порцию).

Как объяснить backpressure в требованиях к системе?

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

Есть ли backpressure в Kafka?

Да, но реализован он на стороне потребителя. Consumer сам вызывает poll() и забирает столько, сколько успевает обработать; необработанные сообщения остаются в топике до истечения retention. Продюсер не блокируется напрямую медленным консьюмером — они развязаны хранением сообщений, поэтому Kafka часто и выбирают, чтобы сгладить разницу в скоростях.

Это официальная информация?

Нет. Статья основана на спецификации Reactive Streams, документации Project Reactor, RxJava, Kafka и общей практике проектирования систем. Конкретные формулировки вопросов зависят от компании и уровня позиции.


Тренируйте системный анализ — откройте тренажёр с 1500+ вопросами для собесов.