> Что такое consumer group в брокерах сообщений (Go)

Уровень: junior · Роль: backend · Язык: Go · Категория: Технические вопросы

Компании: Wildberries

Стек: Go

> Пример ответа

Короткий ответ

Consumer group - это механизм горизонтального масштабирования потребления сообщений из топика. Группа объединяет несколько consumer-инстансов, которые совместно читают партиции: каждая партиция обрабатывается только одним consumer'ом из группы. Это позволяет распределять нагрузку и гарантировать, что каждое сообщение будет обработано ровно один раз в рамках группы. При добавлении или удалении consumer'ов происходит ребалансировка партиций.

Подробное объяснение

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

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

  • Одна партиция - один consumer в рамках группы. Если партиций меньше, чем consumer'ов, часть consumer'ов будет простаивать.
  • Гарантия порядка сохраняется только внутри партиции. Если порядок сообщений критичен, они должны попадать в одну партицию (например, по ключу).
  • Ребалансировка происходит автоматически при изменении состава группы: новый consumer подключается, старый уходит или происходит сбой.
  • Offset (смещение) хранится на стороне брокера для каждой партиции и группы. Это позволяет consumer'у продолжить чтение с места остановки после перезапуска.

В Kafka consumer group реализована через протокол координации: один из брокеров выступает координатором группы, он назначает партиции и отслеживает heartbeat'ы участников.

В RabbitMQ аналогом является consumer group из плагина Quorum Queues или использование конкурентных consumer'ов на одном queue - но там модель другая: сообщение из очереди получает только один consumer, а группа просто увеличивает пропускную способность.

На практике

В Go с Kafka (библиотека segmentio/kafka-go или confluent-kafka-go) consumer group настраивается через конфигурацию:

  • GroupID - идентификатор группы.
  • SessionTimeout - время, после которого consumer считается мёртвым, если не прислал heartbeat.
  • RebalanceTimeout - время на завершение обработки текущих сообщений при ребалансировке.

Типичный паттерн - запуск нескольких горутин, каждая со своим consumer'ом, но с одинаковым GroupID. Брокер сам распределит партиции между ними.

Важно: обработка сообщения должна быть идемпотентной, потому что при ребалансировке возможна повторная доставка (at-least-once семантика по умолчанию).

Пример кода

GO
package main
import (
"context"
"fmt"
"log"
"os"
"os/signal"
"syscall"
"github.com/segmentio/kafka-go"
)
func main() {
// Конфигурация consumer group
reader := kafka.NewReader(kafka.ReaderConfig{
Brokers: []string{"localhost:9092"},
GroupID: "payment-processor",
Topic: "orders",
MinBytes: 10e3, // 10KB
MaxBytes: 10e6, // 10MB
})
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// Обработка сигналов для graceful shutdown
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
go func() {
<-sigCh
cancel()
}()
for {
msg, err := reader.ReadMessage(ctx)
if err != nil {
if ctx.Err() != nil {
break
}
log.Printf("read error: %v", err)
continue
}
// Обработка сообщения
processOrder(msg.Value)
// Явный коммит offset (по умолчанию auto-commit)
if err := reader.CommitMessages(ctx, msg); err != nil {
log.Printf("commit error: %v", err)
}
}
reader.Close()
}
func processOrder(data []byte) {
fmt.Printf("processing order: %s\n", string(data))
}

Для запуска нескольких consumer'ов в одной группе достаточно запустить несколько экземпляров этого приложения или несколько горутин с отдельными kafka.Reader.

Как отвечать на собеседовании

Начни с определения: consumer group - это способ распределения нагрузки между потребителями. Затем объясни ключевое правило: одна партиция обрабатывается одним consumer'ом группы. Упомяни ребалансировку и offset'ы. Если спросят про гарантии - скажи, что порядок сохраняется только внутри партиции, а доставка по умолчанию at-least-once.

Для junior достаточно уверенно объяснить базовую модель и зачем это нужно. Если спросят про Go - покажи, что знаешь, как настроить kafka.Reader с GroupID.

Что проверяет интервьюер

  • Понимание модели партиционирования и распределения нагрузки.
  • Знание гарантий доставки и порядка.
  • Понимание механизма ребалансировки и его последствий.
  • Умение объяснить разницу между consumer group и простым consumer'ом.
  • Для Go-разработчика - знание конкретной библиотеки и её API.

Типичные ошибки

  • Утверждение, что consumer group дублирует сообщения всем участникам - это неверно, дублирование возможно только между разными группами.
  • Игнорирование факта, что при ребалансировке возможна повторная обработка сообщений.
  • Утверждение, что порядок сообщений гарантируется глобально - порядок гарантируется только в пределах партиции.
  • Путаница между consumer group в Kafka и конкурентными consumer'ами в RabbitMQ - в RabbitMQ нет партиций, сообщение из очереди получает один consumer.
  • Забывают упомянуть, что количество consumer'ов в группе не должно превышать количество партиций, иначе часть будет простаивать.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью