RabbitMQ – Ordre de livraison des messages

Je dois choisir un nouveau courtier Queue pour mon nouveau projet.

Cette fois, j’ai besoin d’une queue évolutive qui prend en charge pub / sub, et il est essentiel de conserver l’ordre des messages.

J’ai lu le commentaire d’Alexis: Il écrit:

“En effet, nous pensons que RabbitMQ fournit des commandes plus fortes que Kafka”

J’ai lu la section de commande des messages dans rabbitmq docs:

“Les messages peuvent être renvoyés à la queue à l’aide des méthodes AMQP dotées d’un paramètre de queue (basic.recover, basic.reject et basic.nack) ou d’une fermeture de canal en cas de messages non acquittés … il est toujours possible pour des consommateurs individuels d’observer des messages en dérangement si la queue comporte plusieurs abonnés, ceci étant dû aux actions des autres abonnés qui peuvent mettre en queue les messages. ”

Si je dois traiter des messages par leur commande, je ne peux utiliser rabbitMQ avec une queue exclusive que pour chaque consommateur?

Est-ce que RabbitMQ est toujours considéré comme une bonne solution pour la mise en queue des messages commandés?

Eh bien, examinons de plus près le scénario que vous décrivez ci-dessus. Je pense qu’il est important de coller la documentation immédiatement avant l’extrait de code dans votre question pour fournir un contexte:

La section 4.7 de la spécification de base AMQP 0-9-1 explique les conditions dans lesquelles la commande est garantie: les messages publiés dans un canal, passant par un échange et une queue et un canal sortant seront reçus dans le même ordre qu’ils ont été envoyés. RabbitMQ offre des garanties plus solides depuis la version 2.7.0.

Les messages peuvent être renvoyés dans la queue à l’aide des méthodes AMQP dotées d’un paramètre de queue (basic.recover, basic.reject et basic.nack), ou en raison de la fermeture d’un canal lorsque des messages non acquittés sont conservés. Tous ces scénarios ont entraîné la remise en queue des messages à l’arrière de la queue pour les versions de RabbitMQ antérieures à 2.7.0. A partir de la version 2.7.0 de RabbitMQ, les messages sont toujours dans la queue dans l’ordre de publication, même en présence d’une mise en queue ou d’une fermeture de canal. (soulignement ajouté)

Il est donc clair que RabbitMQ, à partir de la version 2.7.0, apporte une amélioration plutôt radicale par rapport à la spécification AMQP originale en ce qui concerne le classement des messages.

Avec plusieurs consommateurs (parallèles), l’ordre de traitement ne peut être garanti.
Le troisième paragraphe (collé dans la question) continue en donnant un avertissement, que je paraphraserai: “si vous avez plusieurs processeurs dans la queue, il n’y a plus de garantie que les messages seront traités dans l’ordre.” Tout ce qu’ils disent, c’est que RabbitMQ ne peut pas défier les lois des mathématiques.

Considérez une ligne de clients dans une banque. Cette banque en particulier est fière d’aider les clients dans l’ordre dans lequel ils sont entrés dans la banque. Les clients font la queue dans une queue et sont servis par l’un des trois guichets disponibles.

Ce matin, les trois caissiers sont devenus disponibles en même temps et les trois clients suivants se sont approchés. Soudainement, le premier des trois scrutateurs est devenu violemment malade et n’a pas pu finir de servir le premier client de la ligne. Au moment où cela se produisait, le guichet 2 avait fini avec le client 2 et le guichet 3 avait déjà commencé à servir le client 3.

Maintenant, l’une des deux choses peut se produire. (1) Le premier client en ligne peut revenir en tête de la ligne ou (2) le premier client peut préempter le troisième client, ce qui fait que ce dernier cesse de travailler sur le troisième client et commence à travailler sur le premier. Ce type de logique de préemption n’est pas pris en charge par RabbitMQ, ni par aucun autre courtier de messages dont je suis au courant. Dans les deux cas, le premier client ne finit pas par être aidé en premier – le deuxième client le fait, ayant la chance d’avoir un bon caissier rapide. La seule façon de garantir aux clients une aide est d’avoir un guichet unique pour aider les clients un par un, ce qui entraînera des problèmes de service client majeurs pour la banque.

J’espère que cela aide à illustrer le problème que vous posez. Il est impossible de s’assurer que les messages sont traités dans l’ordre dans tous les cas possibles, étant donné que vous avez plusieurs consommateurs. Peu importe que vous ayez plusieurs files d’attente, plusieurs consommateurs exclusifs, différents courtiers, etc., il n’y a aucun moyen de garantir a priori que les messages soient traités dans l’ordre avec plusieurs consommateurs. Mais RabbitMQ fera de son mieux.

L’ordre des messages est conservé dans Kafka, mais uniquement dans les partitions plutôt que globalement. Si vos données nécessitent à la fois un classement global et des partitions, cela complique les choses. Toutefois, si vous avez juste besoin de vous assurer que tous les mêmes événements pour le même utilisateur, etc., se retrouvent dans la même partition afin qu’ils soient correctement ordonnés, vous pouvez le faire. Le producteur est responsable de la partition sur laquelle il écrit, donc si vous pouvez partitionner logiquement vos données, cela peut être préférable.

Je pense qu’il y a deux choses dans cette question qui ne sont pas similaires, l’ordre de consommation et l’ordre de traitement.

Les Message Queues peuvent, jusqu’à un certain degré, vous garantir que les messages seront consommés dans l’ordre, mais qu’ils ne peuvent cependant pas vous garantir l’ordre de traitement.

La principale différence réside dans le fait que certains aspects du traitement des messages ne peuvent être déterminés au moment de la consommation, par exemple:

  • Comme mentionné, un consommateur peut échouer lors du traitement, ici l’ordre de consommation du message était correct, cependant, le consommateur n’a pas réussi à le traiter correctement, ce qui le ramènera à la queue et jusqu’à présent, l’ordre de consommation est intact. t savoir comment l’ordre de traitement est maintenant

  • Si, par “traitement”, nous entendons que le message est maintenant complètement éliminé, examinez le cas où votre temps de traitement n’est pas linéaire, autrement dit, le traitement d’un message prend plus de temps qu’un autre. anticipés, les messages 4 et 5 peuvent être consommés et terminer le traitement avant que le message 3

Ainsi, même si vous avez réussi à renvoyer le message au début de la queue (qui viole la commande de consommation), vous ne pouvez toujours pas garantir que tous les messages avant le message suivant ont été traités.

Si vous souhaitez assurer l’ordre de traitement alors:

  1. N’avoir qu’une seule instance de consommateur à tout moment
  2. Ou n’utilisez pas de queue de messagerie et effectuez le traitement dans une méthode de blocage synchrone, ce qui peut sembler anormal, mais dans de nombreux cas, les exigences métier sont totalement valides et parfois même critiques.