Подтверждения (acks) и идемпотентный продюсер

Урок про надёжность записи: сколько подтверждений ждать и как не насоздавать дубликатов при повторах.

acks — настройка продюсера, задающая, сколько реплик должны подтвердить запись, прежде чем она считается успешной; идемпотентный продюсер гарантирует, что повтор отправки не создаст дубликат.

Зачем это нужно

Сеть ненадёжна: ответ брокера может потеряться, и продюсер повторит отправку — а сообщение, возможно, уже записано. Без защиты это даёт дубликаты. А параметр acks определяет, насколько вы уверены, что запись вообще переживёт сбой брокера. Это два ключевых рычага надёжности на стороне записи.

Уровни acks

acksЖдём подтверждения отРиск
0никого (выстрелил и забыл)потеря данных, максимум скорость
1только лидерапотеря, если лидер упал до репликации
all (-1)лидера и всех ISR-репликнадёжно, чуть выше задержка

Для важных данных — acks=all: запись подтверждена, только когда её получили все синхронные реплики, и падение одного брокера её не теряет.

Проблема дубликатов при ретрае

  Продюсер -> [записать M] -> Брокер: записал M (off 5)
  Брокер -> ack ...X (ack потерялся в сети)
  Продюсер: "ответа нет" -> повтор [записать M]
  Брокер: записал M снова (off 6)  -- ДУБЛЬ!

Идемпотентный продюсер

Включение enable.idempotence=true решает это. Продюсер получает уникальный producer id и нумерует сообщения порядковыми номерами на партицию. Брокер запоминает последний принятый номер и отбрасывает повтор с уже виденным номером — запись произойдёт ровно один раз, несмотря на ретраи.

# надёжный продюсер без дублей
acks=all
enable.idempotence=true
retries=2147483647
max.in.flight.requests.per.connection=5

Как работает под капотом

При идемпотентности каждое сообщение несёт пару (producer id, sequence number) на партицию. Брокер хранит последний записанный sequence для этой пары; если приходит сообщение с номером, который уже записан (ретрай), брокер отвечает «ок», но повторно не пишет — дубль не попадает в лог. Номера строго возрастают, поэтому брокер также ловит «дыры» (пропуск номера) и сигнализирует об ошибке. Идемпотентность работает в пределах одной сессии продюсера и одной партиции; межпартиционные и кросс-сессионные гарантии даёт уже транзакционный продюсер (основа exactly-once).

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

  • acks=1 для критичных данных. Если лидер упал до репликации, подтверждённая запись теряется.
  • Ретраи без идемпотентности. Повторы при потерянных ack плодят дубликаты в логе.
  • acks=0 «ради скорости». Это режим без гарантий: часть событий молча пропадёт под нагрузкой.

Итоги

  • acks задаёт надёжность записи: 0 — быстро и без гарантий, all — переживает падение брокера.
  • Ретраи без защиты создают дубликаты; идемпотентный продюсер их устраняет нумерацией сообщений.
  • Надёжный профиль: acks=all + enable.idempotence=true.
Проверьте себя
1. Что гарантирует acks=all?
AМаксимальную скорость без подтверждений
BЗапись подтверждена всеми синхронными репликами (ISR) и переживает падение лидера
CУдаление дубликатов
DСжатие сообщений
2. Откуда берутся дубликаты при ретраях продюсера?
AИз-за сжатия
BAck потерялся, продюсер повторил отправку, а сообщение уже было записано
CИз-за многих партиций
DИз-за консьюмер-групп
3. Как идемпотентный продюсер убирает дубликаты?
AСжимает повторы
BНумерует сообщения (producer id + sequence); брокер отбрасывает уже виденный номер
CУдаляет топик
DОтключает ретраи