Skip to content
Gallery
Theory for java developer
Share
Explore

icon picker
Kafka

Kafka и брокеры сообщений.

Message broker =
Брокеры сообщений
Есть множество способов передавать информацию между микросервисами, один из самых надежных и простых являются брокеры сообщений. Server = broker.
Работают по схеме producer – consumer(subscriber).
image.png
Есть много определений Kafka:
Распределенный, высоконагруженный, отказорустойчивый + платформа обработки потоковой информации / лог / система обмена сообщениями между серверными приложениями в режиме реального времени.
Благодаря высокой пропускной способности, масштабируемости и надежности применяется в компаниях, работающих с большими объемами данных. Написана на языках Java и Scala.
Разница по сравнению с другими брокерами сообщений.
Kafka и RabbitMQ. Схема: «producer—consumer» и обеспечивают репликацию сообщений.
Kafka — pull (получатели сами достают из топика сообщения). Хранит сообщения. Для для сбора и агрегации событий из множества источников, метрик и логов.
RabbitMQ — push (отправляет сообщения получателям). Удаляет сообщения при доставке. Для быстрого обмена сообщениями между несколькими сервисами.
Таким образом, Apache Kafka позволяет множеству потребителей читать одни и те же данные независимо, и такой паттерн удобен, например, в event-driven-системах.
Строение
Message / Record / Event – Сообщение которое отправляет producer в topic
Key – (any) Специальное значение, для распределения по партициям(при 1 партиции, не нужен)
Value - (any) Само тело сообщения.
Timestamp – дата и время проставляется брокером когда сохраняется сообщение.
Headers – пользовательские пары Key(string) – value(any). Для дополнительной информации.
Offset – индекс сообщения в партиции топика, проставляется брокером при сохранении сообщения – последний оффсет +1. Использует consumer при вычитке сообщений в составе consumer-group. Подробнее ниже.
image.png
Topic - это логическое объединение партиций 0...n, а partition— фактическая единица хранения. То, что физически хранится на диске в виде нескольких файлов.
Patition – Лог(Последовательный журнал), куда записывается сообщение взависимости от колюча. Механизм партиций позволяет кафке работать распараллелено со множеством консьюмеров и быть отказоустойчивой.
Запись сообщения в партицию топика.
1.1 Message нет key, partition = 3 -> round robin, порядок не гарантирован в рамках partition
1.2 Message содержит key, partion = 5 -> Очень похоже на распределения по бакетами в hashMap.
Вычисление hash ключа сообщения чтобы записи с одинаковым ключом попадали в одну партицию.
После создания топика появится папка с темже названием, а внутри папки партиций. Если зайти в partition-0 увидим 3 файла log из одного segment-а (если мы не отправляли много сообщений).
image.png
После отправки сообщения увидим что kafka просто записала сообщение в 3 файла.
Это файлы, сжатые для производительности. Прочитаем через утилиту в кафке.
image.png
offset=0 , timestamp=165695..., key=15, payload = Welcome...
Если отправить еще сообщение оно просто сохранится ниже с offset на 1 больше последнего.
image.png
Segment in partition
Segment – это части на которые делится сама партиция.
В отличие от нескольких больш
image.png
ых файлов - сегменты решают проблемы производительности и удаления старых сообщений.
Segment состоит из 3 файлов - name.log, name.index и name.timeindex, заместо name - следующий offset после закрытия последнего сегмента.
.index - для быстрого доступа к сообщению по offset, без сканирования всего файла .log (default 1Gb). (Байтовое смещение).
.timeindex – тоже самое но по времени.
Хранение сообщений в partition
Messages в логе храняться не всегда, а удаляются через время или по достижению установленного порога байт. Удалять сообщения из кафки руками плохая практика.
Гарантия доставки
at-most-once(максимум 1 раз)
enable.auto.commit = true
auto.commit.interval.ms=low value
auto.commit=true NOT consumer.commitSync() from the consumer
Если consumer взял сообщение и в нем произошла ошибка, сообщение будет потеряно.
at-least-once также возможен, с такойже конфигурацией – consumer обработал сообщение и сделал рестатр, до автоматического коммита – consumer прочитает сообщения еще один раз.
Producer – если продусер не производит повторную отправку по истечению тайм аута. Сообщение не будет доставлено в брокер.
at-least-once(минимум 1 раз)
enable.auto.commit = false NEED consumer.commitSync() from the consumer
consumer взял сообщение обработал его и упал, не сделав commit. Он прочитает его опять.
Producer – если acks=all и продусер получил подтверждение от брокера – записано однократно.
Но если подтверждения нет, продусер может попробовать еще один раз, будет дубликат
exaclty-once(точно 1 раз) с 0.11 version
Produce
enable.idempotence=true
Эпохи продюсера.
Иденпотентность работает так – каждый пакет отправленный в кафку содержит порядковый номер. При помощи которого брокер устраняет дубликаты данных. Порядковый номер сохраняется в лог.
Транзакции – можно отправлять сообщения в несколько разделов (партиций) так что все сообщения будут видны любому либо никому
Consumer
isolation level – есть два способа чтения транзакционных сообщений
read_committed – считывать транзитивные сообщения после коммита транзакции
read_uncommitted – считывать все сообщения без ожидания коммита
Механизм exactly-once — он только для producer-ов, то есть если producer по какой-то причине не уверен, сохранилось ли сообщение в кафку (например разрыв соединения), он просто перепошлёт сообщение в кафку с тем же ID и механизм exactly-once гарантирует, что event не будет продублирован
Полагаю что вопрос всё же был про consumer-ов.
Здесь кафка не даёт гарантий exactly-once и consumer должен сам позаботиться чтобы не обработать одну и ту же запись несколько раз. Для этого можно использовать offset, который есть у каждого event-а и который монотонно растёт. То есть клиент может у себя в хранилище сохранять последний обработанный offset и по нему фильтровать дубли
Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
CtrlP
) instead.