Что такое Consumer Group в Apache Kafka?

Ответ

Consumer Group (группа потребителей) в Apache Kafka — это логическая абстракция, объединяющая один или несколько потребителей (KafkaConsumer) для совместного потребления сообщений из одного или нескольких топиков. Основная цель — обеспечение масштабируемости и отказоустойчивости при параллельной обработке потоков данных.

Ключевые принципы:

  1. Распределение партиций: Все партиции топиков, на которые подписана группа, равномерно распределяются между ее потребителями. Каждая партиция в любой момент времени потребляется только одним потребителем из группы.
  2. Масштабируемость: Количество потребителей в группе можно увеличивать до количества партиций в подписанных топиках. Новый потребитель автоматически получит свою долю партиций (произойдет rebalance).
  3. Отказоустойчивость: Если один из потребителей отключается (краш, остановка), его партиции будут перераспределены между оставшимися активными потребителями в группе.

Пример: Топик orders имеет 4 партиции (P0, P1, P2, P3).

  • Группа order-processors с 1 потребителем: Этот единственный потребитель будет читать сообщения со всех 4 партиций.
  • Группа order-processors с 2 потребителями:
    • Consumer 1 может читать P0 и P2.
    • Consumer 2 может читать P1 и P3.
  • Группа order-processors с 4 потребителями: Каждый потребитель получит ровно одну партицию.
  • Группа order-processors с 5+ потребителями: 4 потребителя получат по партиции, а 5-й и последующие будут простаивать (так как партиций больше нет).

Важные аспекты:

  • group.id: Уникальный идентификатор группы, задаваемый для каждого потребителя при создании.
  • Координатор группы и лидер: Один из брокеров Kafka выступает в роли координатора группы, который управляет присоединением потребителей и перераспределением партиций.
  • Смещения (offsets): Kafka хранит позицию (смещение) последнего успешно обработанного сообщения для каждой партиции в каждой группе. Это позволяет группе продолжить чтение с нужного места после перезапуска.
  • Два основных паттерна:
    • Конкурирующие потребители (Queue pattern): Все потребители в одной группе совместно обрабатывают данные из топика, распределяя нагрузку.
    • Публикация-подписка (Pub-Sub pattern): Каждая группа получает все сообщения из топика независимо от других групп. Для этого нужно использовать разные group.id.

Ответ 18+ 🔞

Давай разберём эту вашу группу потребителей, а то как будто про какую-то секту речь, а не про технологию.

Представь себе пиццерию, блядь. Топик — это конвейер с готовыми пиццами. Партиции — это четыре полосы на этом конвейере: пепперони едет по одной, маргарита по другой, и так далее.

Так вот, Consumer Group — это, сука, бригада голодных курьеров, которые эти пиццы разбирают.

Как это работает, ёпта:

  1. Один курьер на всю бригаду (1 потребитель в группе). Мужик один, пиздец как запарится. Бегает как угорелый между всеми четырьмя лентами, хватает пепперони, потом маргариту, потом ещё чего. Всю работу тянет на себе, герой, блядь. Но если он упадёт без сил — пиццы так и поедут в никуда, всё, пиздец доставке.

  2. Два курьера (2 потребителя). Уже веселее. Координатор (это такой старший по смене, который на брокере сидит) говорит: «Вась, ты бери первую и третью ленту. Петь, тебе вторая и четвёртая». И каждый спокойно своё забирает, не мешая друг другу. Одну пиццу с одной ленты два курьера хватать не будут — это святое правило.

  3. Четыре курьера (4 потребителя). Идеальная картина, ёбана! Каждому досталось по одной ленте, работа кипит, все при деле.

  4. Пять курьеров (5+ потребителей). А вот тут начинается пиздец и махинации. Четыре ленты, пять ртов. Четверо работают, а пятый, бедолага, ходит слоном, пиццу ему не дают, потому что свободных лент нет. Он просто простаивает, как хуй в бане, и ресурсы жрёт. Зачем его нанимали — загадка.

А теперь про важные фишки, без которых нихуя не понятно:

  • group.id — это типа нашивка на куртке, название твоей бригады. «Волки», «Молния», «Гориллы». Все, у кого одинаковые нашивки, работают вместе, внутри одной команды, и пиццы делят между собой.
  • А если нашивки РАЗНЫЕ? А вот это, сука, ключевой момент! Если приходит другая бригада, скажем, «Упыри», с таким же group.id — они влезут в распределение пицц с «Волками». А если у них свой уникальный group.id (например, «Маньяки»), то для них, блядь, запустят второй, такой же конвейер с пиццами! Они будут забирать точные копии тех же пепперони и маргарит. Это и есть паттерн «Публикация-Подписка»: одна пицца — много независимых бригад-подписчиков.
  • Смещения (offsets) — это, блядь, гениально. Это как если бы каждый курьер, забрав пиццу, ставил галочку в блокнотике: «Пепперони с ленты №1, заказ №15 забрал». Упал, отрубился, его сменили — новый парень посмотрит в блокнот, увидит «№15 забрано», и спокойно возьмёт следующую, №16. Ни одна пицца не потеряется и не придётся начинать с начала конвейера.
  • Ребаланс (rebalance) — это когда в бригаде что-то меняется. Пришёл новый курьер или один сдох. Старший (координатор) орет: «ВСЕ СТОП, ЁБАНАРОТ! Перераспределяем ленты!». Все на секунду останавливаются, получают новые задания, и работа продолжается. Болезненная, но необходимая хуйня.

Код, его не трогаем, он святой:

Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("group.id", "order-processors"); // Нашавка "Волки"
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");

KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
consumer.subscribe(Arrays.asList("orders")); // Подписываемся на конвейер "orders"

Короче, суть в чём: Группа (group.id) — это способ заставить несколько жрунов (consumer'ов) мирно и без драк поделить один поток данных (партиции топика) между собой. А если хочешь, чтобы жруны получали всё подряд, не делясь — дай каждому свою уникальную группу, и пусть жрут, блядь, сколько влезет.