Les messages ordonnés permettent aux consommateurs de traiter les messages exactement dans l'ordre d'envoi. ApsaraMQ for RocketMQ utilise des groupes de messages pour définir la portée de l'ordonnancement : les messages appartenant au même groupe sont toujours livrés de manière séquentielle, tandis que les messages provenant de groupes différents sont traités indépendamment.
Cas d'utilisation
Utilisez les messages ordonnés lorsque les systèmes en aval doivent traiter les événements exactement dans la séquence où ils se sont produits en amont :
-
Appariement des transactions -- Dans le trading de titres financiers, lorsque plusieurs offres partagent le même prix, la règle « premier arrivé, premier servi » s'applique. Le système de traitement des commandes doit gérer les offres exactement dans l'ordre de placement.

-
Synchronisation incrémentielle des données -- Lors de la réplication des modifications de base de données (insertions, mises à jour, suppressions) via une file d'attente de messages vers un système de recherche, les opérations doivent être rejouées dans leur ordre d'origine. Une relecture désordonnée génère un état incohérent.


Fonctionnement de l'ordonnancement
L'ordonnancement des messages de bout en bout comporte deux volets : l'ordre de production (côté envoi) et l'ordre de consommation (côté réception). Ces deux conditions doivent être remplies pour garantir un traitement strict selon le principe premier entré, premier sorti (FIFO).
Ordre de production
Pour garantir l'ordre de production, respectez les trois conditions suivantes :
Même groupe de messages -- Définissez le même groupe de messages pour tous les messages qui doivent être ordonnés les uns par rapport aux autres. Les messages appartenant à des groupes différents n'ont aucune relation d'ordre entre eux.
Producteur unique -- Envoyez tous les messages connexes depuis un seul producteur. Même avec le même groupe de messages, les messages provenant de producteurs différents dans des systèmes distincts n'ont pas d'ordre déterministe.
Envoi sériel -- Envoyez les messages de manière séquentielle depuis un seul thread. Bien que le client producteur prenne en charge l'accès multithread, les messages envoyés en parallèle depuis différents threads n'ont pas d'ordre déterministe.
Lorsque ces conditions sont réunies, les messages partageant le même groupe de messages sont stockés dans la même file d'attente, dans l'ordre d'envoi.

Comportement de stockage :
Les messages du même groupe sont stockés de manière séquentielle dans la même file d'attente.
Les messages de groupes différents peuvent coexister dans la même file d'attente, mais leur ordre relatif n'est pas garanti.
Dans le schéma ci-dessus, le Groupe de messages 1 (G1-M1, G1-M2, G1-M3) et le Groupe de messages 4 (G4-M1, G4-M2) partagent la File d'attente 1. ApsaraMQ for RocketMQ garantit l'ordre au sein de chaque groupe, mais pas entre les groupes.
Ordre de consommation
Pour garantir l'ordre de consommation, deux mécanismes agissent de concert :
-
Ordre de livraison -- Le SDK et le protocole serveur livrent les messages dans l'ordre de stockage. Respectez scrupuleusement le schéma réception-traitement-accusé de réception. Un traitement asynchrone peut rompre la garantie d'ordre.
ImportantAvec PushConsumer, les messages sont livrés un par un dans l'ordre de stockage. Avec SimpleConsumer, plusieurs messages peuvent arriver lors d'une seule opération d'extraction (pull) ; votre application doit les traiter de manière séquentielle et accuser réception de chacun d'eux avant d'appeler à nouveau
receivepour le même groupe. Pour plus de détails, consultez Types de consommateurs. -
Nombre limité de tentatives -- Lorsqu'un message ordonné échoue après le nombre maximal de tentatives, il est ignoré afin de débloquer les messages suivants. Choisissez un nombre de tentatives qui équilibre la fiabilité et le risque de bloquer l'intégralité du groupe. Les tentatives au sein d'un groupe de messages :
Ne perturbent pas la garantie d'ordre.
N'affectent pas les messages des autres groupes de messages.
Bloquent les messages suivants du même groupe jusqu'à ce que le message actuel soit résolu.
ImportantPendant qu'un message ordonné ayant échoué fait l'objet de nouvelles tentatives, les messages suivants du même groupe sont bloqués. Ils ne sont livrés qu'après la réussite du message actuel ou l'épuisement de ses tentatives.
Combinaisons d'ordres de production et de consommation
Le respect strict du principe FIFO exige à la fois l'ordre de production et l'ordre de consommation. Toutefois, tous les consommateurs n'ont pas besoin d'une livraison ordonnée. Adaptez la configuration en fonction du débit et des exigences d'ordonnancement :
| Ordre de production | Ordre de consommation | Résultat |
|---|---|---|
| Groupe de messages défini ; envoi sériel | Ordonné | FIFO strict au sein de chaque groupe de messages |
| Groupe de messages défini ; envoi sériel | Concurrent | Ordre chronologique approximatif ; débit plus élevé |
| Aucun groupe de messages ; envoi non ordonné | Ordonné | Ordonnancement strict au niveau de la file d'attente (correspond à l'ordre de stockage, pas à l'ordre d'envoi) |
| Aucun groupe de messages ; envoi non ordonné | Concurrent | Ordre chronologique approximatif |
Cycle de vie des messages
Un message ordonné traverse cinq états :

Initialisé -- Le producteur construit le message et se prépare à l'envoyer.
Prêt -- Le message arrive sur le broker et devient visible pour les consommateurs.
En cours de traitement -- Un consommateur récupère le message et le traite. Si le broker ne reçoit aucun accusé de réception dans le délai imparti, il retente la livraison. Pour plus de détails, consultez Tentatives de consommation.
Accusé de réception -- Le consommateur valide le résultat. Par défaut, ApsaraMQ for RocketMQ conserve tous les messages. Le broker marque le message comme consommé, mais ne le supprime pas immédiatement.
Supprimé -- À l'expiration de la période de rétention ou lorsque l'espace de stockage vient à manquer, le broker supprime les messages les plus anciens de manière progressive. Avant la suppression, les messages peuvent être reconsummés. Pour plus de détails, consultez Stockage et nettoyage des messages.
Un message faisant l'objet d'une nouvelle tentative est traité comme un nouveau message. Le cycle de vie du message d'origine prend fin.
Pendant qu'un message ordonné fait l'objet de nouvelles tentatives, les messages suivants du même groupe sont bloqués jusqu'à ce que le message actuel aboutisse.
Limites
Les messages ordonnés ne peuvent être envoyés qu'aux rubriques dont le paramètre MessageType est défini sur FIFO. Le type de message doit correspondre au type de rubrique.
Si un groupe de consommateurs est configuré pour une livraison ordonnée, tous les messages consommés par ce groupe sont facturés en tant que messages ordonnés, quel que soit leur type réel. Si un ordonnancement strict n'est pas requis, configurez le groupe pour une livraison concurrente afin de réduire les coûts.
Prérequis
Avant de commencer, assurez-vous d'avoir :
Une rubrique dont le paramètre MessageType est défini sur FIFO, créée dans la console ApsaraMQ for RocketMQ
Un groupe de consommateurs configuré pour une livraison ordonnée (requis uniquement si vous avez besoin d'une consommation ordonnée)
Le SDK gRPC RocketMQ 5.x installé dans votre projet
Les messages ordonnés ne peuvent être envoyés qu'aux rubriques dont le paramètre MessageType est défini sur FIFO. Un groupe de consommateurs qui n'est pas configuré en mode de livraison ordonnée livre les messages de manière concurrente. Vérifiez à la fois le type de rubrique et le mode de livraison du groupe de consommateurs avant d'écrire tout code.
Optimiser la concurrence de consommation
Avec le SDK gRPC RocketMQ 5.x, PushConsumer peut distribuer les messages provenant de la même MessageQueue à différents threads en fonction de leur groupe de messages. Plus vos valeurs de groupe de messages sont distinctes, plus le gain de débit est important.
Versions de SDK prises en charge :
| SDK | Version minimale |
|---|---|
| Java | 5.0.8 |
| C++ | 5.0.3 |
| Autres SDK | Non pris en charge |
Envoyer et consommer des messages ordonnés
Les messages ordonnés nécessitent un groupe de messages à chaque appel d'envoi. Concevez des groupes de messages avec la granularité la plus fine permise par votre activité métier -- par exemple, utilisez un ID de commande ou un ID utilisateur. Cela permet un ordonnancement par entité tout en maximisant le parallélisme entre les différentes entités.
Tous les exemples ci-dessous utilisent Java. Pour des exemples complets de SDK dans d'autres langages, consultez le SDK gRPC RocketMQ 5.x.
Exemple de code
Dépanner les tentatives de consommation
Les tentatives de consommation ordonnée pour PushConsumer ont lieu côté client -- le serveur n'enregistre pas les détails des tentatives. Si une trace de message affiche un résultat de livraison failed, vérifiez les journaux du client consommateur.
Pour connaître le chemin d'accès aux journaux du client, consultez Configuration des journaux.
Recherchez les mots-clés suivants dans les journaux du client :
Message listener raised an exception while consuming messages
Failed to consume fifo message finally, run out of attempt times
Bonnes pratiques
Traiter les messages de manière sérielle, pas par lots
Consommez un message à la fois. La consommation par lots peut rompre l'ordonnancement.
Exemple : Les messages sont envoyés dans l'ordre 1 -> 2 -> 3 -> 4. Lors de la consommation par lots, les messages 2 et 3 sont traités ensemble et échouent. Lors de la nouvelle tentative, les messages 2 et 3 sont tous deux redistribués -- mais le message 2 pourrait être traité à nouveau après que le message 3 a déjà réussi lors d'une autre tentative, ce qui entraîne une consommation hors ordre.
Répartir les groupes de messages pour éviter les points chauds
ApsaraMQ for RocketMQ utilise la valeur du groupe de messages pour déterminer quelle file d'attente côté serveur stockera chaque message. Tous les messages d'un même groupe sont routés vers la même file d'attente. Concentrer trop de messages dans quelques groupes surcharge ces files d'attente, créant des points chauds de stockage et limitant la scalabilité.
Utilisez des clés à grain fin comme groupes de messages -- par exemple, des ID de commande ou des ID utilisateur. Plus vos valeurs de groupe de messages sont distinctes, plus les messages sont répartis uniformément entre les files d'attente. Cela permet de maintenir l'ordre des messages pour une même entité tout en répartissant la charge entre les files d'attente pour différentes entités.