Можно ли менять offset в Kafka и стоит ли это делать?
Что проверяют
Знаете ли вы, как consumer хранит позицию и как её сдвинуть в коде, а не только в теории. Следом спрашивают про семантику доставки: что будет с дублями после перемотки и как сделать обработку безопасной.
Как отвечать
Коротко про модель: offset это номер записи в партиции, группа потребителей фиксирует свою позицию в топике __consumer_offsets. Зафиксированный offset указывает на следующую запись к чтению, то есть это номер последней обработанной плюс один.
Инструменты в Java-клиенте:
seek(TopicPartition, long): переставляет позицию для следующегоpoll(). ЕстьseekToBeginning()иseekToEnd(), аoffsetsForTimes()находит offset по метке времени;- где вызывать: только для назначенных партиций, обычно в
ConsumerRebalanceListener.onPartitionsAssigned(). Иначе клиент броситIllegalStateException; - фиксация: по умолчанию
enable.auto.commit=trueс интерваломauto.commit.interval.msв 5 секунд. Для контроля её отключают и вызываютcommitSync()илиcommitAsync()после обработки; - Spring Kafka:
ConsumerSeekAwareдля перемотки,AckMode.MANUALдля ручной фиксации,DefaultErrorHandlerсDeadLetterPublishingRecovererвместо ручного пропуска битых сообщений; - снаружи:
kafka-consumer-groups.sh --reset-offsets --execute, но только при остановленной группе.
Стоит ли: да, для повторной обработки после бага, загрузки истории новым сервисом, отладки. Но при условии, что обработчик идемпотентен: перемотка назад гарантированно даст дубли, вперёд даст пропуск. Для цепочки «прочитал, обработал, записал в Kafka» есть транзакции и sendOffsetsToTransaction(). Это даёт exactly-once внутри Kafka, но не для записи во внешнюю базу.
Где спотыкаются
Фиксируют offset обработанной записи, а не следующей. После рестарта последняя запись каждый раз обрабатывается повторно.
Вызывают seek() сразу после subscribe(). Партиции назначаются только внутри poll(), и вызов падает.
Путают риски местами: перемотка назад означает дубли, а не потерю. Потеря возникает при сдвиге вперёд или когда записи обрабатываются в другом потоке, а автофиксация уже закоммитила их позицию.