Consumer Groups Kafka : Traitement Parallèle et Coordination
Les consumer groups sont le mécanisme qui permet à Kafka de distribuer le travail entre plusieurs instances d'une application. C'est ce qui rend Kafka scalable côté consommation.
Qu'est-ce qu'un Consumer Group ?
Définition
Un consumer group est un ensemble de consumers qui travaillent ensemble pour consommer un topic. Chaque message n'est traité que par un seul consumer du groupe.
Topic "orders" (3 partitions)
┌─────────────────────────────────────────────────────────────┐
│ P0 │ P1 │ P2 │
└─────────────────────────────────────────────────────────────┘
│ │ │
│ │ │
▼ ▼ ▼
┌──────────────────────────────────────────────────────────────┐
│ Consumer Group "order-processing" │
├────────────────┬─────────────────┬───────────────────────────┤
│ Consumer 1 │ Consumer 2 │ Consumer 3 │
│ (lit P0) │ (lit P1) │ (lit P2) │
└────────────────┴─────────────────┴───────────────────────────┘
Pourquoi des consumer groups ?
1. Scalabilité horizontale Ajouter des consumers pour augmenter le throughput de traitement.
2. Haute disponibilité Si un consumer tombe, les autres reprennent automatiquement ses partitions.
3. Isolation entre applications Différents groupes peuvent lire le même topic indépendamment.
Assignation des partitions
Règle fondamentale
Dans un consumer group, une partition ne peut être assignée qu'à un seul consumer. Mais un consumer peut avoir plusieurs partitions.
Scénarios d'assignation
Cas 1 : Autant de consumers que de partitions (optimal)
Partitions: P0 P1 P2
│ │ │
Consumers: C1 C2 C3
Chaque consumer traite une partition. Distribution équilibrée.
Cas 2 : Moins de consumers que de partitions
Partitions: P0 P1 P2 P3
│ │ └──┬──┘
Consumers: C1 C2 C3
Certains consumers traitent plusieurs partitions.
Cas 3 : Plus de consumers que de partitions
Partitions: P0 P1 P2
│ │ │
Consumers: C1 C2 C3 C4 (idle)
Des consumers restent inactifs. Ils servent de backup.
Stratégies d'assignation
Kafka propose plusieurs stratégies pour distribuer les partitions :
| Stratégie | Comportement | Cas d'usage |
|---|---|---|
| Range | Assignation contiguë par topic | Plusieurs topics similaires |
| RoundRobin | Distribution circulaire équilibrée | Distribution uniforme |
| Sticky | Minimise les réassignations | Stabilité lors des rebalances |
| CooperativeSticky | Rebalance progressif | Production (recommandé) |
Rebalancing
Qu'est-ce que le rebalancing ?
Le rebalancing est le processus de redistribution des partitions quand la composition du groupe change :
- Un consumer rejoint le groupe
- Un consumer quitte le groupe
- Un consumer est considéré mort (timeout)
- Les partitions du topic changent
Déroulement d'un rebalance
État initial : 3 partitions, 3 consumers
┌────┐ ┌────┐ ┌────┐
│ P0 │ │ P1 │ │ P2 │
└──┬─┘ └──┬─┘ └──┬─┘
│ │ │
C1 C2 C3
Consumer C2 tombe (ou quitte)
│
▼
REBALANCE DÉCLENCHÉ
│
▼
État final : Redistribution
┌────┐ ┌────┐ ┌────┐
│ P0 │ │ P1 │ │ P2 │
└──┬─┘ └──┬─┘ └──┬─┘
│ └──┬───┘
C1 C3
Impact du rebalancing
Pendant un rebalance :
- Stop-the-world (stratégies classiques) : Tous les consumers arrêtent de traiter
- Latence : Temps de coordination
- Risque de duplication : Messages en cours de traitement
C'est pourquoi le Cooperative Sticky est recommandé : il permet un rebalance incrémental sans arrêt complet.
Group Coordinator
Rôle du coordinator
Le Group Coordinator est un broker responsable de la gestion d'un consumer group :
- Maintenir la liste des membres
- Détecter les members morts
- Déclencher les rebalances
- Stocker les offsets commités
Chaque consumer group a un coordinator déterminé par :
coordinator_broker = hash(group.id) % nb_partitions(__consumer_offsets)
Heartbeats et session timeout
Les consumers envoient des heartbeats pour signaler qu'ils sont vivants.
| Paramètre | Défaut | Description |
|---|---|---|
session.timeout.ms |
45000 | Temps avant qu'un consumer soit déclaré mort |
heartbeat.interval.ms |
3000 | Fréquence des heartbeats |
max.poll.interval.ms |
300000 | Temps max entre deux polls |
Timeline :
├────┼────┼────┼────┼────┼────┼────┼────┼────┤
HB HB HB HB HB ...
│ │ │ │ │
└────┴────┴────┴────┴──── Si pas de HB pendant
session.timeout → mort
Plusieurs consumer groups
Indépendance des groupes
Différents consumer groups lisent le même topic indépendamment. Chaque groupe maintient ses propres offsets.
Topic "orders" (3 partitions)
┌─────────────────────────────────────────────────────────────┐
│ P0 │ P1 │ P2 │
└─────────────────────────────────────────────────────────────┘
│ │ │
┌─────┼─────────────────────┼─────────────────────┼─────┐
│ │ │ │ │
│ ▼ ▼ ▼ │
│ Consumer Group "order-processing" │
│ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │ C1 │ │ C2 │ │ C3 │ │
│ └─────┘ └─────┘ └─────┘ │
└───────────────────────────────────────────────────────┘
┌─────┼─────────────────────┼─────────────────────┼─────┐
│ │ │ │ │
│ ▼ ▼ ▼ │
│ Consumer Group "analytics" │
│ ┌─────┐ ┌─────┐ │
│ │ A1 │ │ A2 │ │
│ └─────┘ └─────┘ │
└───────────────────────────────────────────────────────┘
Chaque message est donc traité :
- Une fois par "order-processing"
- Une fois par "analytics"
Cas d'usage
| Pattern | Description |
|---|---|
| Microservices | Chaque service = un groupe |
| ETL | Source → Kafka → Plusieurs destinations |
| Replay | Nouveau groupe pour retraiter depuis le début |
Gestion des offsets en groupe
Stockage des offsets
Les offsets des consumer groups sont stockés dans un topic interne : __consumer_offsets.
Structure stockée :
Key: (group_id, topic, partition)
Value: (offset, metadata, timestamp)
Commit et reprise
Quand un consumer commet un offset, il est associé au groupe :
Consumer Group "order-processing"
├── Topic: orders
│ ├── Partition 0: offset 1523
│ ├── Partition 1: offset 1847
│ └── Partition 2: offset 1392
Si C1 (qui lisait P0) tombe et C2 reprend P0 :
- C2 commence à l'offset 1523 (dernier commité)
- Pas de messages perdus (si commit après traitement)
Lag du consumer group
Le lag est la différence entre le dernier message publié et le dernier offset commité.
Partition P0 :
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
│ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
▲ ▲
committed latest
(offset 4) (offset 9)
│ │
└──────── LAG = 5 ─────────┘
Un lag croissant indique que les consumers ne suivent pas le rythme des producers.
Bonnes pratiques
Dimensionnement
-
Nombre de partitions ≥ nombre de consumers max
- Si vous prévoyez 10 consumers, créez au moins 10 partitions
-
Commencer avec peu de consumers
- Ajouter des consumers selon le lag observé
Configuration
| Objectif | Configuration |
|---|---|
| Stabilité | partition.assignment.strategy=CooperativeStickyAssignor |
| Réactivité | Réduire session.timeout.ms (attention aux faux positifs) |
| Throughput | Augmenter max.poll.records |
| Latence | Réduire fetch.min.bytes |
Monitoring
Métriques clés à surveiller :
| Métrique | Seuil d'alerte |
|---|---|
| Consumer lag | Croissance continue |
| Rebalance frequency | > 1/heure en production |
| Commit latency | > 1 seconde |
| Poll interval | Proche de max.poll.interval.ms |
Résumé
| Concept | Description | Impact |
|---|---|---|
| Consumer Group | Ensemble de consumers coordonnés | Scalabilité du traitement |
| Partition assignment | Distribution partitions → consumers | Parallélisme |
| Rebalancing | Redistribution lors de changements | Disponibilité |
| Group Coordinator | Broker gérant le groupe | Coordination |
| Lag | Retard de traitement | Indicateur de santé |
Série complète
Vous avez terminé la série "Fondamentaux Kafka" :
- ✅ Qu'est-ce que Kafka ? - Introduction et concepts
- ✅ Architecture - Brokers, Topics, Partitions
- ✅ Producers & Consumers - Envoi et lecture
- ✅ Consumer Groups - Traitement parallèle (cet article)
Pour aller plus loin, explorez les articles avancés sur le monitoring, la sécurité et les patterns de production.
Cet article fait partie de la série "Fondamentaux Kafka" qui explique les concepts de base de manière progressive et accessible.