Содержание

С вас вопросы, с нас ответы. Часть 12

Отвечаем на популярные вопросы про Kafka
Консультирует:
Андрей Серебрянский, ведущий разработчик в Яндекс

1. Чем Kafka отличается от RabbitMQ, ArtemisMQ и других брокеров сообщений?

Эти системы сильно отличаются внутренним устройством и архитектурой, но для разработчиков важны, прежде всего, два практических отличия.

Первое — RabbitMQ масштабируется значительно хуже, чем Kafka. Если на RabbitMQ вы можете выдерживать тысячи сообщений в секунду в очереди, то Kafka способна обеспечивать десятки тысяч, сотни тысяч и даже миллионы сообщений в секунду. Это связано с тем, что Kafka масштабируется горизонтально. Один топик может располагаться сразу на нескольких брокерах, чего в RabbitMQ нет.

Второе фундаментальное отличие важно уже на этапе проектирования архитектуры. В RabbitMQ после того, как сообщение вычитано, оно сразу удаляется из очереди. А в Kafka сообщение хранится заданный период времени — по умолчанию 7 дней. В течение этого времени его можно читать сколько угодно раз.

То есть в Kafka можно один раз записать сообщение, а затем отдать его десяткам или даже сотням потребителей.

Кроме того, из-за этой особенности RabbitMQ сложнее дебажить. Если вы не понимаете, обработано сообщение или нет, вы не можете просто пойти в брокер и посмотреть — сообщение уже удалено. В Kafka же вы всегда знаете, под каким offset находится сообщение, и можете посмотреть его в течение retention-периода, а также проверить, обработал ли его конкретный consumer.

2. Как Kafka обеспечивает высокую производительность и масштабируемость?

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

Например, если у вас 10 серверов, на каждом может находиться по одной партиции. Таким образом, нагрузка на запись и чтение распределяется между всеми машинами.
То есть данные пишутся не в одну машину, а сразу во все машины, где находятся партиции топика. За счет этого нагрузка равномерно распределяется по кластеру и не появляются hot spot-ы (перегруженные сервера).

3. Как выбрать количество партиций для топика?

Хороший принцип — ориентироваться на количество читателей.

Скорость чтения конкретного consumer’а — это скорость чтения одной партиции. Например, если в один топик записывается 10 МБ/с, а consumer способен читать только 2 МБ/с, значит, потребуется минимум 5 партиций.

Но количество партиций лучше увеличивать еще и с запасом на лаг. Например, если consumer несколько часов по какой-то причине не работал, потом ему придется догонять накопившиеся данные. Для этого желательно иметь запас производительности, например, в два раза.

Если читателей пока нет и ориентироваться не на что, можно смотреть на объем записи.
Практический принцип — не записывать в одну партицию больше 1 МБ/с, потому что такую нагрузку consumer обычно способен стабильно обрабатывать.

Но и заранее создавать слишком много партиций не стоит. Чем больше партиций и данных хранит Kafka, тем сложнее восстановление после сбоев.

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

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

4. Как Kafka гарантирует доставку сообщений At Most Once, At Least Once и Exactly Once?

At Most Once, или режим Fire and Forget («отправил и забыл»), гарантируется только настройками producer. Для этого используется:
acks=0
То есть producer отправляет сообщение и не ждет подтверждения ни от одного брокера. Он просто отправляет и забывает.

В таком режиме сообщение будет доставлено максимум один раз, но может не доставиться вообще, если по пути произойдет ошибка.

At Least Once гарантируется настройкой:
acks=all
Но этого недостаточно.

На топике дополнительно нужно настроить:
min.insync.replicas=2
То есть сообщение считается записанным только тогда, когда его получили как минимум две синхронные реплики.

Также желательно использовать:
replication.factor=3
Тогда данные будут храниться на трех репликах внутри кластера Kafka.
Once-доставки в Kafka нет. Но существует Exactly Once Processing.

Например, когда мы читаем из одного топика, обрабатываем данные и записываем их в другой.

Kafka умеет транзакционно закоммитить offset и записать данные в целевые топики. Все операции либо выполняются полностью, либо не выполняются вообще.

5. Что происходит при падении брокера Kafka?

Под падением здесь имеется в виду жесткий отказ. Например, сервер просто выключили из розетки, пропало питание или отключился дата-центр.

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

Если не были настроены min.insync.replicas=2, потери становятся вполне реальными.

Во-вторых, брокер перестает быть лидером для части партиций.

А лидер в Kafka — это именно та реплика, через которую идет запись и чтение.

После отказа кластеру нужно:
  • обнаружить, что один из брокеров стал недоступен;
  • выбрать новых лидеров партиций;
  • уведомить клиентов;
  • дождаться переподключения producer’ов и consumer’ов.

На практике жесткий отказ может вызывать задержки 2−6 секунд.

Если используется старая Kafka с ZooKeeper и десятками тысяч партиций, подобная миграция может занимать минуты.

Поэтому при большом количестве партиций имеет смысл использовать современные версии Kafka с KRaft.

6. Как Kafka гарантирует порядок обработки сообщений?

В Kafka действует следующая гарантия: все сообщения, записанные в одну партицию, будут прочитаны одной consumer-группой в строгом порядке.

При этом между разными партициями такого порядка уже нет.

То есть глобального порядка внутри всего топика Kafka не гарантирует.

Если порядок критичен — связанные сообщения должны попадать в одну партицию.

7. Почему Kafka тормозит и как это диагностировать?

Под словом «тормозит» может скрываться множество разных сценариев.
Может тормозить запись в Kafka. Может тормозить чтение. Может долго устанавливаться соединение. Если Kafka прямо сейчас получает слишком много запросов, они могут вставать в очередь.

Для всего этого существуют метрики: у consumer’а, producer’а, брокера и самого кластера.

Подробно разбирать их здесь сложно — таких метрик десятки и сотни. Но именно они позволяют понять источник проблемы.

8. Как избежать потери сообщений в Kafka?

Главное правило — правильно настроить producer и топик.

Для producer:
acks=all
Для топика:
min.insync.replicas=2
То есть запись считается успешной только тогда, когда сообщение сохранено минимум на две синхронные реплики.

И дополнительно желательно использовать:
replication.factor=3
Такая конфигурация позволяет переживать отказ одного брокера и значительно снижает риск потери данных.

задай вопрос, а мы ответим

другие статьи