Объяснение конфигураций производителя, которые улучшают производительность конвейеров Kafka.

В Gojek мы используем Kafka для решения масштабных задач. Поэтому для нас важна каждая мелочь. Производители в Kafka имеют множество конфигураций, и знание того, когда их использовать, может улучшить производительность вашего конвейера Kafka.

В этом посте давайте проанализируем некоторые из этих конфигураций, которые вы, возможно, не используете, но должны.

Конфигурации производителя

1. Подтверждения

  • acks = 0 → Производитель не ждет никаких подтверждений. В этом случае нельзя гарантировать, что запись была получена брокером. retries config не вступает в силу, так как невозможно узнать, произошел ли какой-либо сбой.
  • acks = 1 → Посредник выдает подтверждение после того, как он записывает запись. Однако он не ждет завершения репликации. Это означает, что в случае отказа лидера до завершения репликации запись будет потеряна.
  • acks = all или -1 → Посредник выдает подтверждение после того, как он записывает запись, а также синхронизируется со всеми подписчиками. Этот режим при использовании вместе с config min.insync.replicas обеспечивает высокую надежность. Он определяет минимальное количество реплик, которые должны подтвердить запись, чтобы запись считалась успешной.
Consider the following case
Number of brokers = 3
Replication factor = 3
min.insync.replicas = 2 (This includes the leader)
acks = all
You can tolerate only one broker going down. In case more than one broker goes down then either NotEnoughReplicas or NotEnoughReplicasAfterAppend exception is thrown
  • Повторные попытки и тайм-ауты Если производитель не получает подтверждения, он ожидает время, равное request.timeout.ms, и запрос повторяется. Однако одна проблема во время повторной попытки заключается в том, что порядок запроса может измениться.
Key: Req, Message: 1 -> Done
Key: Req, Message: 2 -> Done
Key: Req, Message: 3 -> Failed
Key: Req, Message: 4 -> Done
Key: Req, Message: 5-> Done
(Retry request)Key: Req, Message: 3-> Done
Expected Order -> 1,2,3,4,5
Actual Order -> 1,2,4,5,3

Если вас не волнует порядок сообщений, то все готово. В противном случае эту проблему можно решить, установив правильное значение для max.in.flight.requests.per.connection. Эта конфигурация определяет максимальное количество неподтвержденных запросов, которые могут быть отправлены в соединении до блокировки. Установка этого значения в 1 означает, что за один раз будет отправляться только запрос, что сохранит порядок.

Добавление подтверждений в конфигурацию вашего производителя может увеличить задержку, так как производитель должен дождаться подтверждения.

2. Идемпотентность

Рассмотрим следующую ситуацию:

В реальном сценарии высока вероятность того, что ваш производитель Kafka не получит подтверждения (возможно, из-за сбоя сети) и попытается выполнить запрос повторно, даже если данные были зафиксированы на брокере. В таком случае происходит дублирование данных. Чтобы справиться с этой ситуацией, вам нужно сделать своего производителя идемпотентным.

Сделать идемпотентных производителей так же просто, как установить config enable.idempotence = true.

Но как это работает?

Каждому производителю назначается идентификатор производителя (PID), который включает его идентификатор каждый раз, когда он отправляет сообщения брокеру. Кроме того, каждое сообщение получает возрастающий порядковый номер (SqNo). На стороне брокера существует другая последовательность для каждого раздела темы. Брокер отслеживает самую большую комбинацию PID-SqNo для каждого раздела. Когда получен более низкий порядковый номер, он отбрасывается.

Идемпотентность имеет следующие конфигурации:

  • acks = all
  • retries = Integer.MAX
  • max.in.flight.requests.per.connection = 1 (0.11 >= Kafka < 1.1) OR 5 (Kafka >= 1.1)

У вас не может быть конфликтующих значений acks и max.in.flight.requests.per.connection при использовании идемпотентности.
Например - вы не можете установить idempotency = true и acks = none для вашего производителя, так как idempotenct ожидает acks = all

3. Дозирование

По умолчанию Kafka пытается отправить записи как можно скорее. Однако это поведение можно изменить, используя два свойства linger.ms и batch.size. Первое свойство определяет, как долго производитель ждет перед отправкой записей в Kafka, тогда как второе определяет максимальный размер пакета, который может быть отправлен за раз. Таким образом, вместо того, чтобы отправить запись как можно скорее, производитель будет ждать linger.ms перед отправкой записи.

Если batch.size будет превышено доlinger.ms, производитель отправит пакет записей.

4. Сжатие

Прежде чем перейти к сжатию, давайте обсудим, почему вы должны это учитывать:

  • Одна из причин - уменьшение занимаемого места на диске.
  • Вы не только сэкономите значительный объем дискового пространства, но и задержка также уменьшится из-за меньшего размера сообщений.

Примечание. Сжатие приводит к увеличению циклов ЦП.

По умолчанию сообщения отправляются без сжатия. Параметр compression.type может иметь значение snappy, gzip или lz4 для сжатия данных перед их отправкой брокерам.

  • Сжатие Snappy было изобретено Google и нацелено на очень высокую скорость и разумное сжатие. Он не нацелен на максимальное сжатие, поэтому уменьшение размера может быть не таким значительным. Если вы ищете алгоритм быстрого сжатия, Snappy может вам подойти.
  • Сжатие Gzip обычно требует больше ресурсов ЦП и времени, но приводит к лучшим коэффициентам сжатия, поэтому его рекомендуется использовать в случаях, когда пропускная способность сети более ограничена.

Настоятельно рекомендуется правильно протестировать эти конфигурации для вашего варианта использования, прежде чем использовать их в производственной среде.

У Стефана Маарека есть несколько действительно интересных блогов / курсов по Kafka, которые я очень рекомендую :)

Вот и все! Спасибо, что прочитали, и я надеюсь, что статья вам понравилась.

Вы также можете подписаться на меня на Medium и Github. 🙂

Хотите, чтобы наши последние сообщения приходили прямо в ваш почтовый ящик? "Подпишитесь на нашу рассылку!"