Ответ
Гарантия доставки At-Least-Once в Kafka достигается за счет комбинации настроек продюсера и механизма подтверждений от брокеров.
Ключевые механизмы:
Повторные отправки (Retries): Продюсер настраивается на повторную отправку сообщений в случае временных сбоев (например, сетевых ошибок). Если продюсер не получает подтверждения от брокера в течение таймаута, он пытается отправить сообщение снова. Для этого параметр
retries
у продюсера должен быть больше 0.Подтверждение от брокера (
acks
): Это самая важная настройка. Она определяет, сколько реплик партиции должны подтвердить запись сообщения, прежде чем продюсер сочтет его успешно отправленным.acks=0
: Продюсер не ждет подтверждения. Возможна потеря данных.acks=1
: Продюсер ждет подтверждения только от лидера партиции. Если лидер падает до того, как реплики скопировали данные, сообщение может быть утеряно.acks=all
(или-1
): Продюсер ждет подтверждения от лидера и всех синхронизированных реплик (in-sync replicas
). Это самая надежная настройка, которая гарантирует, что сообщение не будет потеряно, даже если лидер выйдет из строя.
Идемпотентный продюсер (
enable.idempotence=true
): Механизм повторных отправок может привести к дубликатам (например, брокер записал сообщение, но не успел отправить подтверждение). Чтобы этого избежать, включают идемпотентность. Продюсер присваивает каждому сообщению уникальный порядковый номер. Брокер отслеживает эти номера и отбрасывает дубликаты. Эта настройка фактически приближает гарантию к Exactly-Once на уровне продюсера.
Пример настройки надежного продюсера на Go (библиотека Sarama):
config := sarama.NewConfig()
// 1. Ждать подтверждения от всех синхронизированных реплик.
config.Producer.RequiredAcks = sarama.WaitForAll // acks=all
// 2. Включить повторные отправки при сбоях.
config.Producer.Retry.Max = 5
// 3. Включить идемпотентность для избежания дублей при ретраях.
config.Producer.Idempotent = true
// Для идемпотентности нужно ограничить количество одновременных запросов.
config.Net.MaxOpenRequests = 1
// Обязательно возвращать результат, чтобы отслеживать ошибки.
config.Producer.Return.Successes = true
producer, err := sarama.NewSyncProducer([]string{"kafka:9092"}, config)
Таким образом, связка retries > 0
, acks=all
и enable.idempotence=true
обеспечивает надежную доставку сообщений как минимум один раз, защищая от потерь и дублирования.