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 в разных окружениях.