Kafka consumer lag растёт: очередь или медленная обработка

Дашборд показывает lag 30 000, команда объявляет аварию. Но один consumer может обработать такой хвост за минуту, а другой — за сутки. Разница offset показывает положение чтения в партиции, а не возраст самого старого необработанного события и не срок восстановления. Для решения нужны ещё скорость прихода и скорость обработки.

Возьмём партицию, где сохранённая позиция группы равна 120, а конец доступного журнала — 150. Разница равна 30 позиций. Если за минуту приходит 10 новых записей, а обработчик подтверждает 20, хвост сокращается примерно на 10 в минуту. Если поступает 25, а подтверждается 20, он будет расти, даже когда обработчик исправно работает. Одно значение lag не показывает направление.

Что смотреть по каждой партиции

Сравните за одинаковые интервалы времени текущий end offset, committed offset группы и их изменения. Затем посмотрите длительность обработки записи и возраст самой старой бизнес-записи, ещё не попавшей в целевую систему. В Kafka offsets могут иметь пропуски, например из-за транзакционных маркеров, поэтому разница позиций не всегда буквально равна числу прикладных сообщений.

Если end offset быстро растёт, а committed почти стоит, проверьте логи обработки и внешнюю БД: возможно, одна запись застряла, запись в БД стала медленной или consumer потерял владение партицией. Если обе позиции растут одинаково, lag может оставаться постоянным при стабильной задержке. Если committed скачками догоняет end, возможно, consumer фиксирует offset пачками — график между commit не равен отсутствию полезной работы.

Возраст и бизнес-свежесть

Даже lag 0 не гарантирует свежую витрину. Consumer мог записать данные во временное хранилище, а Spark или последующая загрузка в таблицу отстаёт. Сравните timestamp источника с моментом доступности результата в конечной таблице. Это end-to-end задержка, которая важна пользователю отчёта.

У сообщений тоже есть два времени: когда произошло бизнес-событие и когда producer записал его в Kafka. Если producer отправил вчерашнее событие только сегодня, Kafka lag будет мал, а данные по событийному времени уже опоздали. Для диагностики храните оба timestamp и договоритесь, какую свежесть обещает pipeline.

Масштабировать consumer имеет смысл после локализации партиции. Один горячий ключ может сосредоточить почти все сообщения в одной партиции; дополнительные экземпляры группы не ускорят чтение этой партиции. Если же нагрузка распределена и обработчики упираются в CPU, увеличение числа consumer до числа партиций может помочь. При упоре во внешнюю БД сначала измерьте её пропускную способность.

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

В многопартиционной теме суммарный lag может скрыть одну застрявшую партицию. Выведите таблицу по каждой партиции: end, committed, прирост end и committed за окно, возраст последней подтверждённой бизнес-записи. Сумма нужна для общего масштаба, максимум по возрасту — для пользовательского SLA. Если сообщения одной партиции приходится обрабатывать последовательно, именно её скорость может задавать предел всего конвейера.

Отдельно различайте позицию, прочитанную процессом, и позицию, сохранённую группой. Consumer может получить пачку и ещё работать над ней; значение committed отстаёт от фактического чтения. После перезапуска эта пачка будет прочитана повторно, если commit не состоялся. Поэтому график lag без информации о длительности задачи, ошибках и размерах пачек иногда преувеличивает очередь, но не отменяет потребности в идемпотентной записи результата.

В курсе Data Engineering Fast‑Track вы настраиваете ключи и партиции Kafka, затем проверяете свежесть конвейера Kafka → Spark → lakehouse под управлением Airflow. Откройте программу, чтобы связывать lag с конечной задержкой данных, а не лечить график одним числом.

Если consumer повторяет уже обработанные записи, отдельно разберите момент фиксации offset.

Продолжить на практике

  • Data Engineering Fast‑Track: Kafka → Airflow → Spark ↗

    Практический fast-track по data engineering: за 4–6 недель собираем рабочий конвейер Kafka → Spark → Lakehouse под управлением Airflow. Разберём batch и streaming, окна и watermark, схемы и контракты. Мини‑проекты, Docker Compose, шаблоны DAG и пайплайнов. Курс подойдёт инженерам, аналитикам и тем, кто хочет освоить современные пайплайны данных с уверенным Python.