Kafka Producer

Producer сериализует запись, выбирает партицию, собирает записи в batch и отправляет их лидеру. Его надёжность определяется не одним acks, а сочетанием подтверждений, репликации, retries, идемпотентности и обработки ошибки вызывающим кодом.

Выбор партиции

При заданном ключе partitioner стабильно вычисляет партицию из ключа. При null ключе клиент распределяет записи ради batching и пропускной способности. После увеличения числа партиций прежний ключ может начать попадать в другую партицию.

var record = new ProducerRecord<String, String>(
        "orders",
        orderId,
        json
);
producer.send(record, (metadata, error) -> {
    if (error != null) {
        log.error("Kafka publish failed, eventId={}", eventId, error);
    }
});

Асинхронный send не означает успешную доставку. Ошибку нужно получить через callback или Future; простое отсутствие исключения в вызывающей строке ничего не гарантирует.

Acknowledgements

acksКогда запрос подтверждаетсяОсновной риск
0ответ брокера не ожидаетсянезамеченная потеря
1запись принял лидерпотеря при смене лидера до репликации
allзапись принята текущими ISR по правилам кластераотказ записи при недостаточном ISR

acks=all не означает “ответили все настроенные replicas” и не даёт абсолютной гарантии. Для строгой конфигурации его сочетают с подходящим replication factor и min.insync.replicas.

Retries, порядок и идемпотентность

Сетевой timeout не сообщает, записал ли брокер сообщение. Повтор может создать дубликат. Idempotent producer использует producer id и sequence numbers, чтобы брокер отфильтровал повторную отправку в рамках производительской сессии. Это не делает идемпотентным внешний HTTP-вызов или запись потребителя в БД.

Kafka transaction может атомарно опубликовать записи в несколько партиций и offsets входного consumer group. Для read-process-write конвейера потребитель результата использует read_committed. Любые эффекты вне Kafka требуют отдельного соглашения: idempotency key, inbox/outbox или компенсации.

Производительность

  • batch.size ограничивает размер batch.
  • linger.ms позволяет немного подождать ради более полного batch.
  • compression уменьшает сеть и диск ценой CPU.
  • слишком маленький buffer или медленный broker создаёт backpressure.

Тюнинг начинается с измерения размера сообщения, throughput, latency и частоты ошибок, а не с копирования параметров.

Типичные сбои

  • Игнорировать результат асинхронного send.
  • Включить бесконечные повторы на неретраебельной ошибке.
  • Положить mutable business object в самописный serializer и менять его до фактической сериализации.
  • Считать idempotent producer полной exactly-once гарантией.
  • Использовать ключ с низкой вариативностью и перегреть одну партицию.

Вопросы для собеседования

Почему retry может дать дубль? Клиент мог не получить ack уже принятой записи и отправить её повторно.

Что защищает idempotent producer? От дублей, созданных повторными запросами этого producer в Kafka; не от повторного бизнес-события и не от внешних side effects.

Как ключ влияет на порядок? Одинаковый ключ обычно направляет записи в одну партицию, где Kafka хранит порядок.

Что меняет linger.ms? Добавляет небольшое ожидание, чтобы собрать более крупный batch: throughput может вырасти, latency — тоже.

Когда нужна Kafka transaction? Когда несколько Kafka-записей и/или входные offsets должны фиксироваться атомарно в Kafka.

См. Kafka, Kafka Broker, Кейс конфигурация Kafka в разных окружениях.