Що таке ребаланс і коли він відбувається
на решті партицій, простой тільки для переміщуваних.
Рівень Junior
Визначення
Rebalancing — це процес перерозподілу партицій між консьюмерами в групі.
«Вартість»: під час ребалансу консьюмери НЕ читають повідомлення. При eager rebalancing — повна зупинка на 5-30 секунд. За цей час lag росте, а при cascading failure — лавиноподібно.
До ребалансу:
C1 → P0, P1
C2 → P2, P3
Після додавання C3:
C1 → P0
C2 → P2
C3 → P1, 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. Усі консьюмери revoke свої партиції
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() протягом цього часу
// → вважається мертвим → виключається з групи → ребаланс
Типові помилки
- Часті ребаланси:
Max poll interval exceeded → консьюмер виключений → ребаланс → Простій → втрата продуктивності - Без ConsumerRebalanceListener:
Втрата даних при ребалансі (не закоммічені offsets) - Занадто короткий 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
Архітектурні рішення
- Cooperative rebalancing — стандарт для production
- Static membership — для стабільних інстансів
- Proper tuning — баланс між detection time і false positives
- Monitoring — раннє виявлення проблем
Резюме для Senior
- Rebalancing — критичний процес для availability групи
- Cooperative rebalancing мінімізує disruption
- Group coordinator protocol: join → sync → heartbeat
- Tuning параметрів критичний для стабільності
- Моніторинг частоти ребалансів — ранній індикатор проблем
🎯 Шпаргалка для інтерв’ю
Обов’язково знати:
- 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) — усуває ребаланс при 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 мінімізує disruption
- «Rebalancing не впливає на обробку» — повна зупинка при eager
Пов’язані теми:
- [[5. Що таке Consumer Group]]
- [[6. Як працює балансування консьюмерів у групі]]
- [[8. Що станеться при додаванні нового консьюмера в групі]]
- [[14. У чому різниця між auto commit і manual commit]]