Idées

Tous les consommateurs sont idempotents

Avec Kafka, recevoir deux fois le même message est le cas normal, pas l’exception: chaque consommateur doit être écrit pour qu’une seconde livraison ne change rien

Dans les recommandations Kafka que j’ai rédigées cette année, une ligne paraît excessive à la première lecture: «tous les consommateurs doivent être idempotents, car le risque de recevoir le même message plusieurs fois est très probable».

La réception du même message deux fois passe pour un accident, réservé aux jours de panne. Ce n’en est pas un. C’est le comportement normal du contrat par défaut.

Un consommateur lit un lot, le traite, puis enregistre sa position, son offset. S’il s’arrête entre le traitement et l’enregistrement, ou si son groupe se rééquilibre à ce moment-là, le consommateur qui reprend la partition repart du dernier offset enregistré et traite une seconde fois les mêmes messages. La documentation de Kafka appelle cela «at-least-once», et c’est la garantie par défaut. Un producteur qui réessaie après une erreur réseau peut lui aussi écrire deux fois le même message; le producteur idempotent empêche ce doublon d’entrer dans le journal, mais il ne fait rien pour le consommateur qui s’est arrêté après le traitement.

La réception du même message deux fois n’est pas une défaillance de la plateforme. C’est le revers d’une garantie: aucun message perdu

La question n’est donc pas d’éviter la seconde livraison, mais de savoir ce que fait la seconde livraison. Trois réponses couvrent la plupart des cas. Écrire par clé: une mise à jour sur l’identifiant métier transforme la copie en simple réécriture. Mémoriser ce qui a été fait: enregistrer les identifiants des messages traités dans la même transaction que l’effet, et ignorer ceux déjà vus. Rendre l’effet répétable par nature: fixer un statut plutôt qu’incrémenter un compteur.

L’exactly-once existe bien entre topics Kafka, grâce aux transactions, mais il s’arrête à la frontière de la base ou de l’API dans laquelle le consommateur écrit.

Le test en découle: rejouer deux fois le même message et vérifier que le second passage n’a rien changé.

Sans ce test, le consommateur cache peut-être une erreur que seule la réception du même message deux fois révélera