Pull to refresh

Comments 43

PinnedPinned comments

Обновил статью.

Всё-таки решил дать гарантии доставки здесь, ибо в теоретической статье была бы слишком большая теоретическая вставка :)

Вместо "лидер-последователь" можно говорить "ведущий-ведомый", если всё равно переводите.

И главное непонятно: вот разбили топик (тему?) на 3 раздела (партиции). В какой из разделов попадёт отправленное клиентом сообщение? Запишется во все? Только в один?

Если во все, кто координирует эту запись, есть встроенный load balancer? Если в один, как получается избегать ситуации, где сообщение об остатках на складе записалось в один раздел, а сервис уведомлений читает из другого и это сообщение не получает?

Большое спасибо за ваш комментарий!

Как раз планировал ответить на ваши вопросы в следующей практической статье по Kafka.

Там мы посмотрим на:

  • То, как мы можем влиять на отправку сообщения в конкретный топик с помощью ключа

  • То, что будет, если отправить сообщение без ключа

  • Как работает распределение нагрузки через Consumer Groups

  • Что происходит, когда консьюмеры работают без групп

Ещё раз спасибо!

В какой из разделов попадёт отправленное клиентом сообщение?

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

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

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

Полностью согласен — на практике явное указание партиции требуется крайне редко.

Спасибо, что поделились своими знаниями и опытом! Подобные комментарии делают обсуждение ценным для всех читателей!

Тогда как гарантируется отказоустойчивость? Упал север с 1й партицией, куда было доставлено сообщений, и кроме реплики ничего не спасёт. В чем тогда смысл партиций? Честно, я запутался, я себе это всё иначе представлял.

Я вас понимаю. Давайте попробуем разобраться в этом.

Каждая партиция реплицируется на несколько брокеров с помощью настройки replication factor автоматически. И данные на этих репликах по ходу работы автоматически синхронизируются с лидером. Если брокер, который является лидером партиции упадёт, Kafka сделает лидером партиции один из тех брокер, на которых была реплика этой партиции. Из-за этого I/O операции не прекращаются и все работает хорошо.

Смысл партиций вообще в том, чтобы:

  • Распараллелить обработку между консьюмерами (это повышает пропускную способность)

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

Надеюсь, я вас правильно понял и прояснил непонятные моменты. Если остались вопросы, не стесняйтесь спрашивать!

"Kafka сделает лидером партиции один из тех брокер, на которых была реплика этой партиции. Из-за этого I/O операции не прекращаются и все работает хорошо."
Работает хорошо, только все консьюмеры группы стоят и ждут пока закончатся выборы

Это понятно. Надо же чем-то заплатить за удобство :)

А вообще я говорил конкретно про отказоустойчивость в кластере.

В случае типового кластера скажем из 6 брокеров и 5 контроллеров, гарантировано на каждом брокере будет по 2 реплики . Управлять количествов реплик можно установив по дефолту replication. factor=3. Для крупных проектов желательно использовать несколько ЦОД. И применять в таком случае MirrorMaker. В моём случае у нас нет 3 ЦОД для гарантии доступности топиков. А есть 2 ЦОД. Мы пошли по пути создания 2 кластеров по 6 брокеров и 5 контроллеро, условно назовём их ПРОД и СТАНДИН. Тем самым создали локальный резерв с фактором репликации 4. Даже при падении 2 брокеров и 2 контроллеров кластер остатся в консистентном состоянии, также мы получаем возможность гео резервирования, выведение не обслуживание основного кластера. Пока вопрос синхронизации данных у нас возложен на продуктовые команды.

читать только одну конкретную партицию

Легко - поиск по ключу. Сначала вычисляется партиция, потом ищем только в ней.

Про Кафку была написано:

Многие потребители могут независимо читать одни и те же данные

А в RabbitMq параллельное чтение одних и тех же данных уже запретили?

Сообщения хранятся заданное время

То же самое можно реализовать в RabbitMq.

Если почитать внимательнее документацию RabbitMq, то откроются такие интересные вещи как Exchange - Exchange биндинги и Fanout обмен, которые в умелых руках на многое способны.

P.S.: это не отменяет того факта, что Kafka - классная технология, правда, во многих случаях избыточна.

Отличные замечания!

Вы правы — в RabbitMQ тоже можно организовать параллельное чтение через Fanout Exchange. Однако, в Kafka это поведение по умолчанию, а в RabbitMQ нужно настраивать.

Абсолютно верно — retention policies есть в обоих системах. В Kafka это базовая фича журналирования, в RabbitMQ — дополнительная опция.

Про избыточность огласен на 100%! Kafka действительно избыточна для многих сценариев, где хватило бы RabbitMQ. Выбор всегда зависит от конкретных требований.

Спасибо, что дополнили статью вашим опытом!

За счёт чего несколько консьюмеров могут читать независимо сообщения в одной партиции

В прошлом пункте мы посмотрели на структуру .log файла. В этом файле был так называемый offset. Консьюмеры просто хранят внутри себя значение offset и по нему получают доступ к нужной им информации. Его, разумеется, можно настроить вручную в настройках консьюмера. Мы это обязательно сделаем в следующий раз.

Недопонял этот абзац. Одну партицию может читать только один консьюмер в группе, вы сами выше в статье это подчеркнули. А это про что?

Давайте разбираться :)

Смотрите. Ранее я говорил про Consumer Groups. Там, да, за каждой партицией закрепляется один консьюмер. Но это в рамках одной группы! Если мы добавим другую группу и назначим её на тот же топик, то получится как минимум два консьюмера на каждую партицию (из первой группы и из второй).

Спасибо за ваш вопрос! Надеюсь удалось дать больше понимания!

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

Никак не поможет :)

Мы создаём новую группу не для того, чтобы разгрузить первую. Мы это делаем для того, чтобы эта самая новая группа имела доступ к тем же самым сообщениям, но выполняла другую логику. То есть для независимого чтения одних и тех же данных. Для разгрузки мы увеличиваем количество консьюмеров в рамках одной группы. Тогда уже между ними распределяются партиции и каждый читает свою часть данных.

Читая статью, не покидала мысль: "Что она умеет такого чего не умеет почтовый сервис?"....Прочитал, но не нашел ответа: все это при достаточно прямых руках можно реализовывать на условном Postfix-e. Все задачи, описанные в статье, решаются на почтаре. Тоесть ответ на вопрос описанный в заголовке статьи:"...зачем нужна эта технология?" я так и не получил.

Давайте проведём сравнительный анализ Kafka и Postfix и выделим осовные преимущества Kafka:

  • В Kafka сообщении хранятся неделями

  • В Kafka несколько консьюмеров могут читать одни и те же данные

  • Kafka будет производительность при высоких нагрузках

  • В Kafka можно перечитать сообщение с помощью offset, а в почтаре без отправителя невозможно

Спасибо за ваш комментарий! Надеюсь вам стало понятнее, зачем использовать Kafka!

Ничего не мешает парсить входящие сообщения и раскидывать их по топикам. Важно понимать что кафка это не база данных это транспорт с функцией кеширования данных в размерах ретеншн полиси. У нас политика хранения на проде не более 3 суток. Что соответствует максимальному времени восстановления сервиса для продуктоввх комманд + 1 сутки на выборку лага.

А чем обычный MQTT хуже Kafka и Кролика? И почему сравнивали не с первоисточником протокола, тщательно прописанного в документации по MQTT а с его производными? Что они улучшили? Интересно послушать, наверняка вы это прорабатывали

Отличные вопросы! Давайте разберёмся на конкретных примерах.

MQTT нужен для датчиков, телефонов, умных устройств. Пример: температура с датчика -> включить кондиционер. Он очень лёгкий и работает при условиях постоянной потери связи

RabbitMQ для задач между сервисами. Пример: покупатель сделал заказ -> количество товара на складе уменьшилось. Он гарантирует, что сообщение точно дойдёт.

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

То есть MQTT больше для мира IoT, а RabbitMQ и Kafka для бекенд разработки.

Спасибо за вопросы! Надеюсь, вам стало понятнее!

Для хранения есть продукты предназначенны е для хранения сообщений например ClickHouse,

Приведены аналоги но не прямые. Можно упомянуть про более прямые аналоги вроде RedPanda, у которого по не самым свежим бенчмаркам в 3 раза выше скорость записи и в 20 раз выше скорость чтения.

Классный момент!

RedPanda штука классная. Написана на плюсах, а не на Java и буст в производительности реально ощутим. Апишка совместима с Kafka полностью. В этой статье хотел прояснить лишь базовые моменты, связанные с Kafka. А с кроликом сравнил, чтоб показать различия между обычной очередью сообщений и журналом. Ещё RedPanda достаточно молодая и экосистема не такая широкая. Возможно, в следующих статьях и на неё посмотрим.

Спасибо вам за упоминание этой технологии :)

Это нейросеть пишет и отвечает?

Хах. Да, стиль ответов похож, не спорю. Особенно начало и конец. Но я просто хочу быть вежливым с читателями. А в наше время это ассоциируется с LLM-ками :)

Пролистал вниз, чтобы написать то же самое

Статья - LLM-поделие очень низкого качества. Начинаю брюзжать:

Раздел "как выглядит Kafka-сообщение" ужасен. Очень плохо говорить, что "Kafka сообщение - набор пар ключ-значение", LLM-ка несомненно слышала звон. Каждое отдельное kafka сообщение включает один ключ и одно тело, внутри каждое сообщение не представляет собой Map или json-объект, тело сообщения - любые байты, хотя можно поместить json. У нескольких сообщений может быть совпадающий ключ.

В разделе "Как устроен топик в Kafka и при чём тут масштабируемость" есть некоторая каша между репликацией и шардированием, и потерялся важный факт, что внутри партиции сообщения упорядочены. Что ожидаемо: для выбора, в какой раздел отправится сообщение, используется ключ, а с пониманием роли ключа проблема. И насчёт "после падения сервера Kafka сама перераспределит положение партиций в серверах" - это не так.

Такой маленький, а уже инфоцыганин.

Ценю конструктивную критику, спасибо :)

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

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

В общем, да, есть куда стремиться

Поправил проблемные разделы

Мне кажется, что автор забыл добавить очень важную деталь про гарантии доставки: как продюсер может настраивать acknowledgement, чтобы проверять дошли ли сообщения до брокера, так и консюмеры могут выбирать стратегии (at least/most/once).

Это очень интересная тема :)

Её мы будем рассматривать в следующей практической статье. Там посмотрим на каждую из стратегий. Рассмотрим способы борьбы с дубликатами с помощью механизма идемпотентности. Будет интересно!

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

Было бы не плохо что бы такин статьи были помечены тегом "написано LLM" , что бы их просто игнорировать, тем кто не хочет на такое тратить время.

Здесь интересен практический опыт и субьективное мнение конкретного человека

Буквально все примеры в этой статье взяты из моего недавнего пет-проекта. Ну, за исключением сервиса метрик. В проекте я его не делал. Если не верите, добро пожаловать на гитхаб. В профиле есть ссылка.

Пробежался по верхам, вроде бы неплохая статья, за исключением самого начала: для понимания сути Кафки лучше думать о ней, как о распреденном неизменяемом журнале сообщений (которые неструктурированные массивы байтов), а не систему обмена сообщениями. Из обмена сообщениями следуют неявным образом семантики, Кафке неприсущие, будто бы это очередь. RabbitMQ - для обмена сообщениями, Кафка - для стриминга данных.

Из этого следуют, кажется, конфузы с выбранным примером: не нужно асинхронизировать REST Кафкой, это не очередь задач. Закидывайте в Кафку жирнейший поток данных, чтобы их на другом конце обработать и аггрегировать, это гораздо ближе к задумке. Если Кафку использовать там, где реально синхронность нужна, будет много головной боли на масштабе - например, ребаланс консьюмер групп занимает далеко не нулевое время, а ребаланс нужен каждый раз, когда состав группы меняется. Вы так будете играть с десятком таймаутов, что всё на свете проклянёте.

Согласен с вами. Действительно, слегка запнулся в начале. Поправил статью. Теперь в начале задаю правильный контекст (называю Kafka журналом). Но дальше провожу аналогии с сообщениями, чтобы безболезненно ввести читателя в курс дела.

Спасибо!

Спасибо за статью!

У меня два вопроса:

  1. Что будет если на один топик будут подписаны несколько консумеров, объединенных в разные группы?

  2. Как должен быть настроен консумеры, чтобы читать одно и тоже сообщение из топика ?

Вам спасибо, что прочитали!

  1. Все будет хорошо. Консьюмеры в одной группе не знают о консьюмерах в другой. Чтение будет происходить независимо.

  2. На конкретное сообщение, как мне известно, настроить нельзя. Можно только настроить на топик. О том, как конкретно настроить, используя Spring Boot, я рассказал в своей свежей практической статье. Рекомендую к прочтению :)

Обновил статью.

Всё-таки решил дать гарантии доставки здесь, ибо в теоретической статье была бы слишком большая теоретическая вставка :)

Продублирую тут, т. к. здесь вроде есть знающий люди)

Можно подробнее про 2 основных кейса.

1) Хочу быстрее обрабатывать (чтобы очередь быстрее рассасывалась) => добавляю консьюмеров. Что будет, если просто добавить, без групп, при одной партиции и при нескольких? А если с группами? Что, если партиций три, а в 3 группах по 1, 2 и 3 консьюмера, как они будут назначаться партициям?

2) Хочу, чтобы одно и то же сообщение обрабатывалось несколькими разными сервисами. Что делать?

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

Например, единственный консьюмер упал, после перезапуска Кафка не смогла подобрать ему оффсет, а в очередь за время простоя набежало сообщений. Если брать latest, то не будут обработаны некоторые сообщения. С этой точки зрения всегда удивлялся, как в Кафке выкручиваются, не храня состояние на стороны консьюмеров.

Sign up to leave a comment.

Articles