Что происходит с сообщением в Kafka после его прочтения
Что проверяют
Знаете ли вы, что Kafka это журнал, а не очередь с изъятием. Ответ «сообщение удаляется» сразу показывает, что человек работал с брокером по аналогии с очередями задач и не понимает, зачем тут оффсеты и группы потребителей.
Как отвечать
Главное сказать первым: с сообщением не происходит ничего. Журнал партиции неизменяемый и только дописывается, чтение его не меняет и никак не помечает. Меняется лишь положение потребителя, то есть оффсет, и хранится он отдельно, во внутреннем служебном топике, в разрезе группы и партиции.
Из этого следует:
- другая группа прочитает те же сообщения независимо, а своя группа может перечитать их, если сдвинуть оффсет назад;
- удаляются сообщения по политике хранения, по времени или по объёму, причём целыми сегментами, а не поштучно; при уплотнении по ключу остаётся последнее значение для ключа;
- зафиксированный оффсет означает «следующее к чтению», а не «последнее обработанное».
Дальше про то, во что это превращается в коде на Python. Автоматическая фиксация сдвигает оффсет по таймеру, независимо от того, довели ли вы обработку до конца, поэтому при доставке хотя бы один раз фиксируют вручную и после обработки:
while True:
msg = consumer.poll(1.0)
if msg is None or msg.error():
continue
handle(msg)
consumer.commit(msg, asynchronous=False)Где спотыкаются
Считают, что прочитанное исчезает, и строят на этом логику по принципу «повторно не придёт». Придёт: и после сбоя, и после переназначения партиций, поэтому обработчик обязан быть идемпотентным по ключу.
Оставляют автоматическую фиксацию и называют это доставкой хотя бы один раз. Получается противоположное: падение между фиксацией и завершением обработки теряет сообщение насовсем.
Тянут долгую обработку между вызовами poll. Интервал превышен, координатор считает потребителя мёртвым, партиции уходят другому, незафиксированные сообщения выдаются заново. Лечится это не бесконечным увеличением таймаута, а разбиением работы или паузой на партиции.