Вопрос 15 · Раздел 15

Что такое rebalancing и когда он происходит

на оставшихся партициях, простой только для перемещаемых.

Версии по языкам: English Russian Ukrainian

Уровень Junior

Определение

Rebalancing — это процесс перераспределения партиций между консьюмерами в группе.

«Стоимость»: во время ребаланса консьюмеры НЕ читают сообщения. При eager rebalancing — полная остановка на 5-30 секунд. За это время lag растёт, а при cascading failure — лавинообразно.

До ребаланса:
  C1 → P0, P1
  C2 → P2, P3

После добавления C3:
  C1 → P0, P1
  C2 → P2
  C3 → P3

Когда происходит ребаланс?

1. Добавился новый консьюмер
2. Консьюмер упал или отключился
3. Добавились новые партиции в топик
4. Консьюмер изменил подписку на топики

Что происходит во время ребаланса?

1. Все консьюмеры останавливают чтение
2. Kafka перераспределяет партиции
3. Каждый консьюмер получает новые партиции
4. Чтение возобновляется

Важно: При eager rebalancing — полная остановка. При cooperative (Kafka 2.3+) — обработка продолжается на оставшихся партициях, простой только для перемещаемых.

Пример кода

// Консьюмер автоматически участвует в ребалансе
props.put("group.id", "my-group");
consumer.subscribe(List.of("orders"));
// При добавлении нового консьюмера с тем же group.id
// произойдёт автоматический ребаланс

Уровень Middle

Процесс ребаланса (по шагам)

1. Trigger — событие (новый консьюмер, timeout, etc.)
2. Group coordinator начинает ребаланс
3. Все консьюмеры revokе свои партиции
4. Вычисляется новый assignment
5. Консьюмеры получают новые партиции
6. Чтение возобновляется

Типы ребаланса

Eager Rebalancing (старый):

Все консьюмеры останавливаются полностью
Полное перераспределение партиций
Все консьюмеры продолжают работу
→ Простой всей группы

Cooperative Rebalancing (Kafka 2.3+):

Постепенное перемещение партиций
Консьюмеры продолжают работать с остальными партициями
→ Минимальный простой

ConsumerRebalanceListener

consumer.subscribe(List.of("orders"), new ConsumerRebalanceListener() {
    @Override
    public void onPartitionsRevoked(Collection<TopicPartition> partitions) {
        // Коммитить offsets перед потерей партиций
        consumer.commitSync();
        // Очистить локальные ресурсы
        cleanup(partitions);
    }

    @Override
    public void onPartitionsAssigned(Collection<TopicPartition> partitions) {
        // Инициализация новых партиций
        initialize(partitions);
    }
});

Max Poll Interval Exceeded

// Если обработка батча занимает слишком много времени
props.put("max.poll.interval.ms", "300000");  // 5 минут

// Если консьюмер не вызывает poll() в течение этого времени
// → считается мёртвым → исключается из группы → ребаланс

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

  1. Частые ребалансы:
    Max poll interval exceeded → консьюмер исключён → ребаланс
    → Простой → потеря производительности
    
  2. Без ConsumerRebalanceListener:
    Потеря данных при ребалансе (не закоммичены offsets)
    
  3. Слишком короткий timeout:
    session.timeout.ms=5000 → ложные срабатывания
    → Консьюмер считается мёртвым → ненужный ребаланс
    

Уровень Senior

Internal Implementation

Group Coordinator:

Брокер-координатор хранит состояние группы:
- Member list (список консьюмеров)
- Partition assignments (распределение партиций)
- Committed offsets (в __consumer_offsets)

Протокол ребаланса:

Глоссарий:
  Group Coordinator — брокер, управляющий членством в группе.
  JoinGroup — консьюмер говорит «хочу в группу».
  SyncGroup — лидер рассылает результат распределения.

1. Join Phase:
   - Консьюмер → JoinGroup request
   - Coordinator → собирает всех members
   - Coordinator → выбирает leader группы

2. Assignment Phase:
   - Leader → вычисляет assignment
   - Leader → SyncGroup request
   - Coordinator → рассылает assignments

3. Heartbeat Phase:
   - Консьюмеры → Heartbeat requests
   - Coordinator → подтверждает alive

Cooperative Rebalancing — детально

Incremental Cooperative Rebalancing:

Вместо полной остановки:
1. Revocation части партиций
2. Assignment новых партиций
3. Продолжение работы
4. Повтор при необходимости

Преимущества:
- Минимальный простой
- Сохранение locality данных
- Лучшая availability

Настройка:

props.put("partition.assignment.strategy",
    "org.apache.kafka.clients.consumer.CooperativeStickyAssignor");

Tuning Parameters

# Session management
session.timeout.ms: 30000           # 30 секунд до detection
heartbeat.interval.ms: 10000        # 10 секунд (1/3 от session timeout)

# Poll management
max.poll.interval.ms: 300000        # 5 минут на обработку
max.poll.records: 500               # батч для обработки

# Assignment strategy
partition.assignment.strategy: cooperative-sticky

Failure Scenarios

1. Network Partition:

Консьюмер теряет связь с брокером
→ Heartbeat timeout → session timeout → ребаланс
→ Когда сеть восстанавливается → консьюмер reconnect → join group

2. GC Pause:

session.timeout.ms=30000, GC pause=35 секунд.
Консьюмер 35 секунд не отправляет heartbeat. Broker ждёт 30 секунд → исключает →
ребаланс. После GC консьюмер reconnect → join group → новые партиции.

Long GC pause → консьюмер не отправляет heartbeat
→ Broker считает консьюмер мёртвым → ребаланс
→ После GC консьюмер узнаёт о ребалансе

3. Slow Processing:

Обработка батча > max.poll.interval.ms
→ Broker считает консьюмер мёртвым → ребаланс
→ Консьюмер продолжает → получает新的 assignment

Monitoring Rebalancing

Ключевые метрики:

kafka.consumer.coordinator:num-rebalances
kafka.consumer.coordinator:time-since-last-rebalance
kafka.consumer:assigned-partitions
kafka.consumer:commit-latency-avg

Alerts:

- Ребаланс чаще чем раз в 10 минут → warning
- Ребаланс чаще чем раз в 5 минут → critical
- Консьюмер не отправляет heartbeat > 30s → critical
- Consumer lag растёт → warning

Troubleshooting

1. Определение причины:

// Логи показывают:
"Heartbeat session expired"  session.timeout.ms слишком короткий
"Max poll interval exceeded"  обработка слишком долгая
"Member is dead"  консьюмер упал

2. Решение проблем:

Heartbeat issues:
  → Увеличить session.timeout.ms
  → Проверить network connectivity

Poll interval issues:
  → Уменьшить max.poll.records
  → Оптимизировать обработку
  → Увеличить max.poll.interval.ms

Best Practices

✅ Cooperative rebalancing
✅ Достаточный session timeout (30s+)
✅ Быстрая обработка сообщений
✅ ConsumerRebalanceListener для graceful handling
✅ Static membership для стабильных инстансов
✅ Мониторинг частоты ребалансов

❌ Частые ребалансы без расследования
❌ Eager rebalancing для production
❌ Слишком короткий timeout
❌ Без обработки onPartitionsRevoked
❌ Игнорирование consumer lag

Архитектурные решения

  1. Cooperative rebalancing — стандарт для production
  2. Static membership — для стабильных инстансов
  3. Proper tuning — баланс между detection time и false positives
  4. Monitoring — раннее обнаружение проблем

Резюме для Senior

  • Rebalancing — критический процесс для availability группы
  • Cooperative rebalancing минимизирует disruption
  • Group coordinator protocol: join → sync → heartbeat
  • Tuning параметров критичен для стабильности
  • Monitoring частоты ребалансов — ранний индикатор проблем

🎯 Шпаргалка для интервью

Обязательно знать:

  • Rebalancing — перераспределение партиций между консьюмерами в группе
  • Триггеры: новый консьюмер, падение, таймаут сессии, добавление партиций
  • Eager rebalancing: полная остановка 5-30 секунд; Cooperative: 1-5 секунд, processing продолжается
  • ConsumerRebalanceListener: commitSync в onPartitionsRevoked, cleanup state
  • Max poll interval exceeded — частая причина: консьюмер не вызывает poll() вовремя
  • Group Coordinator protocol: JoinGroup → Assignment (Leader) → SyncGroup → Heartbeat
  • Static membership (group.instance.id) — eliminates rebalance при rolling deploy

Частые уточняющие вопросы:

  • Что такое eager vs cooperative rebalancing? — Eager: все останавливаются. Cooperative: только перемещаемые партиции.
  • Что будет при слишком коротком session.timeout? — Ложные срабатывания, ненужные ребалансы.
  • Как избежать ребаланса при GC pause? — Увеличить session.timeout.ms, static membership.
  • Кто вычисляет assignment? — Leader консьюмер (eager) или Group Coordinator (KIP-848, Kafka 3.0+).

Красные флаги (НЕ говорить):

  • «Ребаланс — это быстро и безболезненно» — 5-30 секунд простоя (eager)
  • «Можно игнорировать частые ребалансы» — признак проблем с таймаутами/обработкой
  • «Eager rebalancing — лучший для production» — cooperative minimizes disruption
  • «Rebalancing не влияет на обработку» — полная остановка при eager

Связанные темы:

  • [[5. Что такое Consumer Group]]
  • [[6. Как работает балансировка консьюмеров в группе]]
  • [[8. Что произойдёт при добавлении нового консьюмера в группе]]
  • [[14. В чём разница между auto commit и manual commit]]