Ответ
Kafka гарантирует доставку сообщения от брокера к консьюмеру (at-least-once), но не может знать, была ли бизнес-логика консьюмера выполнена успешно. Ответственность за подтверждение обработки лежит на самом консьюмере. Это делается через механизм коммита смещений (offset commit).
Offset — это, по сути, закладка, которая указывает, какое сообщение в партиции топика было обработано последним.
Способы управления коммитами:
-
Автоматический коммит (Auto Commit)
- Как работает: Консьюмер автоматически коммитит офсеты через заданный интервал (
auto.commit.interval.ms
). Это поведение включено по умолчанию во многих библиотеках (enable.auto.commit=true
). - Риски: Это самый простой, но и самый ненадежный способ. Если приложение упадет после коммита, но до завершения обработки сообщения, сообщение будет потеряно.
- Как работает: Консьюмер автоматически коммитит офсеты через заданный интервал (
-
Ручной коммит (Manual Commit) — Рекомендуемый подход
- Как работает: Вы отключаете автокоммит (
enable.auto.commit=false
) и явно вызываете методCommit()
после успешной обработки сообщения. Это дает полный контроль над процессом. - Гарантии: Обеспечивает семантику "at-least-once" (как минимум один раз). Если приложение упадет после обработки, но до коммита, то после перезапуска оно снова получит это же сообщение.
// Псевдокод на примере библиотеки confluent-kafka-go for { msg, err := consumer.ReadMessage(-1) if err != nil { // Обработка ошибки continue } // 1. Ваша бизнес-логика по обработке сообщения processMessage(msg.Value) // 2. Если обработка прошла успешно, коммитим офсет // Этот вызов сообщает Kafka: "Я успешно обработал это сообщение и все предыдущие" _, err = consumer.CommitMessage(msg) if err != nil { log.Printf("Failed to commit offset: %v", err) } }
- Как работает: Вы отключаете автокоммит (
Альтернативные паттерны:
-
Использование транзакций (Exactly-Once Semantics): В сценариях "прочитать-обработать-записать" (consume-process-produce) можно использовать транзакции Kafka. Они позволяют атомарно закоммитить офсет прочитанного сообщения и записать результат обработки в другой топик. Либо вся операция проходит успешно, либо ничего не происходит.
-
Отдельный топик для подтверждений (Ack Topic): Консьюмер после обработки отправляет сообщение-подтверждение в специальный
ack-topic
. Другой сервис может слушать этот топик, чтобы отслеживать статус обработки. Этот паттерн усложняет архитектуру, но добавляет гибкости.