Kafka offset out of range после простоя consumer

Consumer не работал неделю. При запуске он пытается читать с сохранённой позиции 20, но в партиции уже остались записи только начиная с позиции 50. Старые данные удалены по политике retention. Никакой retry не вернёт offset 20 из этой темы: прежде чем менять настройку, надо понять, где восстановить промежуток 20–49 и допустим ли его пропуск.

Kafka хранит earliest и end offset для партиции. Если сохранённый offset группы меньше earliest, позиция стала недоступной. В версии конфигурации consumer есть auto.offset.reset. Значение earliest начнёт с первой ещё доступной записи 50. latest перейдёт к концу доступного журнала и пропустит также текущий хвост. none остановит чтение с ошибкой, чтобы оператор принял явное решение.

Почему earliest не означает «прочитать всё»

В примере earliest=50, end=80. Даже если выбрать earliest, записи 20–49 уже отсутствуют в теме. Consumer сможет получить только сохранившийся диапазон 50–79 и новые публикации. Для финансовых событий такой разрыв может испортить итоговую таблицу. Проверьте архив, исходную базу или возможность полного пересчёта из другого достоверного источника.

Если downstream хранит снимок состояния на момент до позиции 50, можно загрузить его и затем дочитать доступный хвост. Важно согласовать точку снимка с позицией Kafka: запись 50 не должна примениться дважды или исчезнуть между снимком и журналом. Если достоверного снимка нет, восстановление может потребовать повторной выгрузки всех бизнес-сущностей из источника.

Диагностика перед сменой настройки

Запишите для каждой партиции сохранённую позицию группы, earliest и end. Разрыв может быть только у одной партиции. Посмотрите фактическое время последнего успешного commit и политику хранения темы. Если consumer отставал ещё до остановки, интервал потери может быть больше длительности самого простоя.

Не выбирайте latest только чтобы приложение стало зелёным: это явно разрешает не читать весь нынешний backlog. Для телеметрии с коротким сроком жизни такой выбор может быть бизнес-допустим, для заказов или оплат — обычно требуется восстановление. Решение должно исходить из того, что будет в конечной таблице, а не из удобства запуска consumer.

На будущее сопоставьте максимальный допустимый простой и темп обработки с retention темы. Если полное восстановление занимает больше срока хранения, даже быстро устранённая авария может закончиться потерей данных. Мониторьте возраст самого старого нужного сообщения и приближение сохранённой позиции к earliest, а не только общий lag.

Если группа только создана и сохранённой позиции у неё никогда не было, auto.offset.reset тоже определяет стартовое поведение. Это другой случай: потерю в результате retention нельзя доказать сравнением с отсутствующим commit. Для старой группы сначала убедитесь, что вы подключились с тем же group.id и к той же теме. Случайно новый идентификатор группы может выглядеть как восстановление, хотя приложение просто начало другое чтение.

План восстановления лучше формулировать по бизнес-идентификаторам. Например, диапазон offset 20–49 мог содержать изменения одних и тех же заказов; число недостающих offset не равно числу потерянных заказов. Сверьте источник и целевую таблицу по ID заказов и версиям состояния. После восстановления пересчитайте контрольные суммы или количество по выбранным интервалам, а не ограничивайтесь тем, что consumer снова дошёл до end.

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

В курсе Data Engineering Fast‑Track группы consumer и модели доставки связаны с последующими Spark-расчётами, проверками свежести и backfill. Посмотрите программу, чтобы планировать восстановление всего конвейера после простоя.

Для другого типа повторной обработки есть разбор дублей при Airflow backfill: там данные ещё доступны, но интервал запускается заново.

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

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

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