Как Kafka определяет, что событие было прочитано
Что проверяют
Понимаете ли вы, что Kafka не помечает сообщения прочитанными и не удаляет их после чтения, а хранит позицию группы потребителей. Следом спрашивают, что будет, если консьюмер упал между обработкой и коммитом.
Как отвечать
Партиция это журнал только на дозапись, у каждой записи там порядковый номер, offset. Брокер не знает, прочитал ли кто-то конкретное сообщение. Он хранит одно число на пару «группа, партиция»: закоммиченный offset.
- где хранится: во внутреннем компактируемом топике
__consumer_offsets, запись принимает координатор группы. ZooKeeper здесь давно не участвует, а в Kafka 4.0 его убрали совсем; - что означает: номер следующего сообщения, которое получит группа, то есть последний обработанный плюс один;
- автокоммит: в Java-клиенте
enable.auto.commit=trueпо умолчанию, коммит раз вauto.commit.interval.ms(5 секунд) внутриpoll(). Коммитится выданное, а не обработанное; - ручной коммит:
commitSync()после обработки пачки илиcommitAsync()с колбэком. Spring Kafka выключает клиентский автокоммит и коммитит сам, режим задаётAckMode: по умолчаниюBATCH, для ручного контроляMANUALиAcknowledgment.acknowledge(); - коммита нет: новая группа начинает с позиции из
auto.offset.reset, по умолчаниюlatest.
Удаление с чтением не связано: сообщения живут по retention.ms (по умолчанию 7 дней) или по размеру, и разные группы читают топик независимо. Lag группы это разница между концом журнала и закоммиченным offset.
Отсюда семантика. Коммит после обработки даёт at-least-once и дубли при ребалансе, коммит до обработки даёт at-most-once и риск потери. Exactly-once внутри Kafka строится на транзакциях: sendOffsetsToTransaction у продюсера и isolation.level=read_committed у читателя.
Где спотыкаются
Говорят, что брокер удаляет сообщение после чтения, как RabbitMQ. В Kafka оно остаётся до истечения retention.
Путают «прочитано» и «закоммичено». С автокоммитом можно закоммитить пачку, которую приложение ещё не обработало, и потерять её при падении.
Не думают об идемпотентности. При at-least-once повтор неизбежен, и обработчик должен спокойно переживать одно сообщение дважды.