Ответ
Offset — это целочисленный идентификатор, присваиваемый каждому сообщению в рамках партиции Kafka. Он служит для отслеживания позиции потребителя (consumer) в партиции.
Основное назначение:
- Отслеживание прогресса: Потребитель хранит (коммитит) offset последнего успешно обработанного сообщения. Это позволяет после перезапуска продолжить чтение с того же места, не теряя данные и не обрабатывая их повторно.
- Гарантия доставки: Управление offset — основа семантики "at-least-once" или "exactly-once" доставки сообщений.
Как это работает:
- Каждая партиция — это упорядоченный, неизменяемый журнал (log).
- Сообщения в журнале получают последовательные offset (0, 1, 2, ...).
- Потребитель читает сообщения по порядку, начиная с сохранённого offset.
- После обработки сообщений потребитель коммитит новый offset (обычно в топик
__consumer_offsets).
Пример кода (Java) с ручным управлением offset:
Properties props = new Properties();
// Отключаем авто-коммит
props.put("enable.auto.commit", "false");
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
consumer.subscribe(Arrays.asList("my-topic"));
while (true) {
ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
for (ConsumerRecord<String, String> record : records) {
// Обработка сообщения
processRecord(record);
}
// Ручной коммит offset для всех обработанных сообщений в этом poll
consumer.commitSync();
}
Важные аспекты:
- Идемпотентность: Повторное чтение с одного offset приведёт к повторной обработке тех же сообщений. Необходима идемпотентная обработка или точное управление коммитом.
- Управление: Offset может коммититься автоматически (риск потери данных при сбое) или вручную (позволяет контролировать момент "подтверждения" обработки).
- Хранение: Offset хранится отдельно от данных сообщения, что позволяет независимо перемещаться по журналу разным потребителям.