Как на стороне consumer-а добиться доставки at-least-once и почему при этом появляются дубли?
- Когда коммитить offset — до или после обработки?
Сначала обработать, потом зафиксировать offset (или подтвердить сообщение). Если упасть между обработкой и фиксацией, сообщение придёт снова — отсюда дубли, и обработка должна быть идемпотентной.
- Фиксация до обработки даёт at-most-once: падение — сообщение потеряно
- enable.auto.commit=true фиксирует по таймеру — возможны и потери, и дубли
- Дубли также при ребалансе и повторах продюсера
А ещё Exactly-once внутри Kafka — транзакции; с внешней базой — offset и результат в одной транзакции
Подробно
Порядок действий определяет гарантию:
- обработать → закоммитить — 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 так сложно достичь?
Разбор темы
- Очереди, pub/sub и гарантии доставки
Зачем брокер сообщений, queue против pub/sub, три семантики доставки, роль идемпотентности и компромисс порядок/масштаб.
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.