Введение
Введение
Глоссарий
- Producer - отправитель сообщений
- Consumer - получатель сообщений
- Broker - сущность отвечающая за получение данных от Producer и отправку их в Consumer
- Topic - аналог очереди в Rabbit
- Partition - независимая часть Topic
- Segment - единица деления Partition на физическом носителе
- Offset - номер сообщения/события в брокере Kafka
- Base offset - начальный номер сообщения в сегменте
- Controller - координирует работу кластера брокеров
- ISR (in sync replica) - реплика, синхронизированная с лидером
- Commit offset - значение последнего оффсета, обработанного Consumer
Отличия от RabbitMQ
- В Rabbit брокер пушит сообщения в консьюмера. В Kafka консьюмер сам забирает сообщения из брокера (poll)
Архитектура Kafka Topic
Topic

Topic делится на партиции (partition). Все партиции независимы, данные пишутся всегда в конец партиции. Сообщения в партиции номеруются по порядку с 0. Номер называется оффсетом (offset) сообщения.
Partition
Вся партиция целиком находится на одном физическом носителе. Но находится она не одним куском данных, а делится на сегменты (segment).

Запись всегда идет в последний сегмент, который называется активным сегментом. Номер начального события в сегменте называется базовым оффсетом (base offset)
Удаление данных
Данные мы можем удалять только целыми сегментами.
На партицию можно настроить ограничение по размеру:
retention.bytes=-1 # По умолчанию нет ограничения
И ограничение по времени:
retention.ms=604800000 # По умолчанию 7 дней
Кафка смотрит на время жизни сегментов и удаляет самые старые, если их время жизни истекло.
Segment
Структура сегмента выглядит следующим образом:

У каждого сегмента хранится 3 файла: название файла содержит базовый оффсет.
Данные хранятся в
.logфайле. События в нем хранятся последовательно, файл работает только на добавление данных в конец.

В файле
.indexхранятся данные для быстрого доступа к оффсетам внутри log-файла.Index record = (relative offset, position)В файле
.timeindexхранятся данные для быстрого доступа по времени
Архитектура Kafka Broker

Каждая партиция на брокере может быть реплицированна. например, с replication factor = 3 и тремя брокерами на каждом брокере будет по одной репликации каждой партиции.
Для того, чтобы записывать на реплицированную партицию, должен быть выбран лидер на одном из брокеров. Лучше выбирать лидеров равномерно по брокерам, так как лидер несет большую нагрузку, так как на них идет начальная запись.
После записи на лидера начинается процесс синхронизации других реплик с лидером. Реплика, синхронизированная с лидером, называется ISR (in sync replica). ISR может участвовать в перевыборе нового лидера, в случае сбоя старого.
[!info]
Если в случае экстренных перевыборов лидеров кластер оказался неравномерным по кол-ву лидеров на брокерах, то Кафка автоматически начнет перебалансировку прозрачно для пользователей.
Архитектура Kafka Producer
Для отправки сообщений можно задать различные уровни гарантий доставки:
enum Acks : int {
None = 0, // Нет гарантий
Leader = 1, // Гарантия, что сообщение записано на лидер
All = -1 // Гарантия, что сообщение записано на все реплики
}
Кол-во реплик, нужных для статуса All может быть задано настройкой топика:
min.insync.replicas = 2 // Достаточно записи на двух репликах
Производительность
В Kafka сообщения отправляются пачкой, для того, чтобы сконфигурировать параметры этой пачки имеются несколько настроек:
- BatchSize - максимальный размер пачки в байтах
- BatchNumMessages - максимальный размер пачки в кол-ве сообщений
- LingerMs - максимальное время, которое мы ожидаем до добавления следующего сообщения в пачку
Если срабатывает хотя бы одно из этих ограничений, то пачка отправляется в брокер. Таким образом можно настраивать продюсера на низкую задержку или на большую пропускную способность.
Архитектура Kafka Consumer
Commit
Консьюмер считывает сообщения из брокера пачками и отдает клиенту их по одному. Клиент обрабатывает сообщение и отправляет Commit обратно в брокер. Commit со значением оффсета сообщения складывается в специальный топик в брокере. Таким образом, если консьюмер упадет, то ему не придется перечитывать все сообщения с нуля.
Это гарантия доставки at least once - мы можем обработать сообщение и упасть, не успев отправить коммит.
Коммит на каждое сообщение не очень эффективен, так как мы сильно увеличиваем траффик. Для решения этой проблемы, у Kafka есть режим 1 коммит на N сообщений. Также, есть возможность делать асинхронные авто-коммиты по времени:
EnableAutoCommit=true
AutoCommitIntervalMs=5000
Если появляется новый консьюмер и у него еще нет коммит оффсета, то он может настроить какое первое сообщение из топика он хочет получить:
enum AutoOffsetReset {
Latest = 0, // берем последнее сообщение
Earliest = 1, // берем первое сообщение
Error = 2 // Возвращаем ошибку.
}
Consumer Group
Коньсюмеры объединенные в одну группу могут делить чтение сообщений. Kafka автоматически балансирует части, которые будут читать разные консьюмеры в группе.
Чего нет в Kafka из коробки
- Отложенные сообщения
- Dead Leter Queue
- AMQP / MQTT
- TTL на одно сообщение
- Очереди с приоритетами