Получить доступ

Как на стороне consumer-а добиться доставки at-least-once и почему при этом появляются дубли?

MiddleОчереди и гарантии доставкиKafka
Ещё спрашивают так:
  • Когда коммитить offset — до или после обработки?
Коротко

Сначала обработать, потом зафиксировать offset (или подтвердить сообщение). Если упасть между обработкой и фиксацией, сообщение придёт снова — отсюда дубли, и обработка должна быть идемпотентной.

  • Фиксация до обработки даёт at-most-once: падение — сообщение потеряно
  • enable.auto.commit=true фиксирует по таймеру — возможны и потери, и дубли
  • Дубли также при ребалансе и повторах продюсера

А ещё Exactly-once внутри Kafka — транзакции; с внешней базой — offset и результат в одной транзакции

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

Порядок действий определяет гарантию:

  • обработать → закоммитить — at-least-once: при падении после обработки, но до коммита, сообщение перечитается и обработается ещё раз;
  • закоммитить → обработать — at-most-once: при падении после коммита сообщение не будет обработано никогда.

Для бизнес-событий почти всегда выбирают at-least-once и делают обработку идемпотентной: дубль безвреден, потеря — нет.

Автокоммит (enable.auto.commit=true) фиксирует offset периодически при очередном poll() — не привязан к завершению обработки. Если обработка асинхронная или пакетная, можно закоммитить ещё не обработанное (потеря) или не закоммитить обработанное (дубли). Для надёжности — ручной коммит после обработки (в Spring Kafka — AckMode.RECORD/BATCH/MANUAL).

Откуда ещё дубли: ребаланс — партицию забрали до коммита, и новый потребитель начнёт с последнего зафиксированного offset; повтор продюсера без идемпотентности; повторная публикация из outbox.

Защита: идемпотентность по id сообщения (таблица обработанных в той же транзакции), естественно идемпотентные операции (UPSERT, установить статус), хранение offset вместе с результатом в базе.

Что хотят услышать

  • Порядок «обработать, потом закоммитить».
  • Почему появляются дубли и откуда ещё.
  • Опасность автокоммита.
  • Идемпотентность как обязательное дополнение.

Частые ошибки

  • Коммитить до обработки «чтобы не было дублей».
  • Полагаться на автокоммит при асинхронной обработке.

Проверьте себя

Один верный вариант. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✓Обработать сообщение и только после этого закоммитить offset; при падении между шагами сообщение придёт снова
  • ✗Закоммитить offset сразу после получения, а потом обработать
  • ✗Включить enable.auto.commit=true — этого достаточно для гарантии
  • ✗Увеличить число партиций топика

Что спросят дальше

  • Как сделать consumer идемпотентным?
  • Почему exactly-once так сложно достичь?

Разбор темы

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем