Потоковые ML-пайплайны для real-time инференса на Kafka, Flink и ONNX

Мы разрабатываем потоковую обработку данных под ключ: события доходят до решения без задержек даже на пиках нагрузки. Сокращаем время реакции систем в разы, а объём ручной работы — на 60%. Остаётесь с работающим контуром, схемами и регламентами.
Часто задаваемые вопросы

Почему потоковая обработка данных ломается на пиках

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

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

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

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

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

Что даёт потоковый контур: измеримый эффект

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

Снижение задержки предсказаний

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

Убранный класс отказов: потери и дубли

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

Сколько ручной работы снимает автопересчёт

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

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

Способы доставки событий: что выбрать под задачу

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

Пакетный режим по расписанию

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

Микропакеты и чистая потоковая схема — где граница

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

Вариант Когда подходит Ограничения
Пакетная обработка по расписанию Отчётность, пересчёт признаков, обучение Задержка равна интервалу запуска
Микропакетный режим Метрики и витрины с задержкой в секунды Опоздавшие события усложняют логику
Чистая потоковая схема Скоринг, реакция на аномалию Состояние, повторы, цена эксплуатации
Гибридный контур Быстрый ответ плюс фоновый пересчёт Нужна сверка потокового и пакетного итога

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

Как мы разворачиваем потоковый контур: этапы работ

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

Аудит источников и профиля нагрузки

  1. Аудит источников данных — инвентаризация топиков, форматов сообщений, ключей партиционирования и доли «грязных» записей. На выходе — карта источников с пометками о задержках и изменениях схем, ломающих обратную совместимость.
  2. Профиль нагрузки — снимаем реальный поток: пики, сезонность, распределение по ключам. Отсюда считаем число параллельных обработчиков и запас по памяти.
  3. Схема потокового контура — фиксируем границы: где читаем, где обогащаем, где вызываем модель, где сохраняем. Отдельно описываем семантику доставки и порядок переигрывания окна при сбое.

Проверка на теневом трафике перед переключением

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

Что остаётся у вас: схемы, регламенты, конфигурации

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

Схемы потоков и описание форматов событий

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

Регламенты реакции на сбои

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

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

Кейс: как сократили задержки на пике нагрузки

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

Что было до и что стало после

Разбор начали с потока: его читали одним потребителем, поэтому масштабировать было нечего. Разнесли обработку на независимые потребители Kafka с ключом партиционирования по идентификатору устройства — порядок событий по одному объекту сохраняется, а нагрузка раскладывается по узлам. Состояние окон вынесли в отказоустойчивое хранилище, и рестарт узла перестал означать потерю накопленного контекста.

Метрика До После
Задержка предсказания на пике рост в 12 раз рост в 1,4 раза
Доля потерянных событий 3–4 % в час пик 0,02 %
Восстановление контура после отказа узла 20–35 минут до 40 секунд

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

Чем потоковая обработка отличается от пакетной?

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

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

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

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

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

Частые технические сомнения перед стартом

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

Что происходит с опоздавшими событиями?

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

Как обеспечивается идемпотентная обработка?

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

Как контролируется качество данных?

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

Выдержит ли контур рост нагрузки?

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

Как запускаете без риска для продакшена?

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

Обсудим задачу и вернёмся с оценкой и планом

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

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

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

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

  • Начинают с выбора инструментов, а не с описания событий. Сначала нужно понять, какие события рождаются, с какой частотой и что считается корректной обработкой, — иначе контур собирается под воображаемую нагрузку и переделывается целиком.
  • Путают потоковую обработку с ускоренной пакетной. Логику периодических прогонов переносят в непрерывный режим как есть: появляются дубли, гонки за одни и те же данные и расхождения между отчётом и экраном.
  • Не разделяют задержку доставки и задержку обработки. Пока эти два показателя измеряют одним числом, непонятно, где узкое место — в транспорте событий или в самом расчёте, и оптимизация бьёт не туда.
  • Тяжёлый пересчёт модели оставляют внутри обработчика событий. Каждое событие тянет за собой полный прогон, и на пике отклик разваливается именно там, где он нужнее всего.
  • Хранят состояние только в памяти обработчика. При перезапуске теряется накопленный контекст окна, и после сбоя показатели уезжают — а восстановить их уже нечем.
  • Не закладывают повторную обработку и «отравленные» события. Один неожиданный формат данных останавливает весь контур вместо того, чтобы уйти в отдельную очередь и разбираться отдельно.
  • Меняют схему событий без обратной совместимости. Добавленное или переименованное поле молча ломает часть потребителей, и узнают об этом по жалобе, а не по проверке.
  • Откладывают наблюдаемость «на потом». Без контроля отставания очереди и прослеживаемости пути события сбой ищут вслепую, поднимая весь контур.
  • Замыкают всё на один узел. Контур не масштабируется добавлением независимых потоков, поэтому рост нагрузки упирается в потолок, а не в ресурсы.
  • Смешивают бизнес-правила и транспорт. Правила расчёта оказываются вписанными в настройки доставки, и любая правка логики требует остановки всего обмена.

Направления AI-разработки

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1542
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1394
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1081
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1368
  • Разработка логотипа компании B2B Advance
    Разработка логотипа компании B2B Advance
    815
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1139