Заметки об Apache Kafka
Apache Kafka — распределенный, масштабируемый и отказоустойчивый лог, способный записывать миллионы записей в секунду. 💪
- Topic: категория сообщений по какому-то типу.
- Broker: кластер (нода).
- Producer: производители публикуют данные в топиках.
- Consumer: потребители это сервисы, которые подписываются на топики.
- Zookeeper: интерфейс координации между брокерами и потребителями Кафки.
Подробнее
Топик
В Кафке, темы разделены и каждый раздел представлен упорядоченным списком последовательных сообщений. Кластер Кафки поддерживает раздельное журналирование (логирование) для каждой темы. Каждому сообщению в разделе присваивается уникальный идентификатор.
Топик это по сути файл, лог. Топик разбит на партиции, нумеруются с нуля. А уже внутри партиции есть сообщения, в пределах одной партиции сообщения приходят по принципу FIFO, FIRST IN, FIRST OUT.
Кафка гарантирует что то что попало в Кафку, из нее не пропадет.
Брокер
Обычно состоит из одного или нескольких серверов, и каждый из них может иметь один или несколько запущенных серверных процесса которые называются брокером. Топики создаются в контексте процессов брокера.
Zookeeper
По сути это распределенная система необходимая для отказоустойчивости брокеров. В этой системе хранятся метаданные необходимые кафке. Например, через нее выбираются лидирующие брокеры для определенных партиций или происходит ребалансировка если отказывает какая-то нода.
Отказоустойчивость
Такая устойчивость возникает за счёт репликаций партиций.
Каждый брокер может быть для партиции лидирующим. И кроме того эти партиции реплицируются на соседние брокеры (по мере возможности). Таким образом запись идет на несколько нод в кластере.
Допустим один из брокеров упал. Что произойдет?
Произойдет ребалансировка, переопределение лидера, а так как у нас есть реплика партиции, то данные мы не теряем и продолжаем читать данные оттуда где они есть. После того как упавший брокер возобновит работу (или мы поднимем новый) у нас произойдет репликация партиции и всё становится как прежде. Через какое-то время ребалансировка снова произойдет.
И это всё работает магически под капотом, нам не нужно думать о том как работает кафка для сохранения наших данных.
Сообщение
- Номер партиции - потому что сообщение отправляется не прямо в топик, а в конкретную партицию.
- Ключ - обычно байтовые значения или гуид. Так то неважно.
- Значение - полезная инфа.
- Заголовки - мета-данные.
Номер партиции можно выбирать самостоятельно так и автоматически через ключ (мы берем ключ, вычисляем хэш-функцию и делим на количество партиций, таким образом записи равномерно распределяется по партициям).
Пропускная способность и время ожидания
Представим, что нам нужно посылать очень много маленьких сообщений. Если мы каждое сообщение будем отправлять как отдельный вызов апи, это будет неэффективно.
Кафка-продюсер умеет группировать сообщения. Мы можем настроить размер группы и время ожидания. По сути это как маршрутка :-)
Запись
Как убедиться что записи отправленные в Кафку вообще там сохранены?
- Простой режим, кафка просто подтверждает что сообщение дошло. Если упал брокер до записи сообщения, то сообщение потеряется.
- При записи. Подтверждаем запись только в момент записи на диск. На случай если хард отлетит.
- Бронебойный. Подтверждаем только когда сообщение реплицировались на все брокеры. Медленно, но гарантия ~100%.
Чем более параноидальный режим тем больше задержка и проблем. Можно отлететь по таймауту. И что выбирать зависит от задачи.
Чтение
Как устроено чтение? Каждый консьюмер входит в какую-то группу.
Если консьюмер один, он читает данные из всех партиций. Но что если данных слишком много?
Мы можем сделать больше консьюмеров. И кафка сама ребалансирует те партиции которые назначены на определенный консьюмер.
Но количество консьюмеров не должно быть больше чем количество партиций. Т.е. число партиций определяет максимальный параллелизм с которым мы можем обрабатывать данные.
Конечно мы можем сделать лишний, но он ничего не будет делать.
Про offset commit
Для надежного чтения предусмотрена такая вещь как офсет коммит.
Вот мы прочитали батч записей, обработали и перед чтением следующего блока в кафку отправляется коммит с офсетом.
Например, консьюмер умер при чтении какого-то сообщения. В таком случае произойдет ребалансировка и сообщения прочитаются с последнего офсета.
Таким образом мы избавляемся от необходимости повторного чтения записей с самого начала, но мы не полностью гарантированы конечно от повторного чтения.
В кафке чтения это запись в служебный топик.
Retention policy
Я говорил что из кафки нельзя удалять сообщения. Но диск не бесконечный. Поэтому в кафке есть такое понятие как ретеншн. Например мы хотим хранить только последний миллион сообщений или гигабайт.
Как только заполняется сегмент, он удаляется.