web-dev-qa-db-fra.com

Comment éviter les messages SQS en double?

Quelle est la meilleure façon d'empêcher les messages en double dans Amazon SQS? J'ai un SQS de domaines en attente d'exploration. avant d'ajouter un nouveau domaine au SQS, je peux vérifier avec les données enregistrées pour voir s'il a été récemment exploré, pour éviter les doublons.

Le problème vient des domaines qui n'ont pas encore été explorés. Par exemple, s'il y a 1000 domaines dans la file d'attente qui n'ont pas été analysés. N'importe lequel de ces liens pourrait être ajouté encore et encore et encore. Ce qui gonfle mon SQS à des centaines de milliers de messages qui sont principalement des doublons.

Comment puis-je empêcher cela? Existe-t-il un moyen de supprimer tous les doublons d'une file d'attente? Ou existe-t-il un moyen de rechercher un message dans une file d'attente avant de l'ajouter? Je pense que c'est un problème que toute personne avec un SQS doit avoir connu.

Une option que je peux voir est si je stocke des données avant que le domaine ne soit ajouté au SQS. Mais si je dois stocker les données deux fois, cela ruine un peu le point d'utiliser un SQS en premier lieu.

35
Marcus Lind

Comme les autres réponses mentionnées, vous ne pouvez pas empêcher les messages en double de passer par SQS.

La plupart du temps, vos messages seront remis à l'un de vos consommateurs une fois, mais vous rencontrerez des doublons à un moment donné.

Je ne pense pas qu'il y ait une réponse facile à cette question, car cela implique de proposer une architecture appropriée capable de faire face aux doublons, ce qui signifie qu'elle est de nature idempotente.

Si tous les travailleurs de votre architecture distribuée étaient idempotents, ce serait facile, car vous n'auriez pas à vous soucier des doublons. Mais en réalité, ce genre d'environnement n'existe pas, quelque part en cours de route, quelque chose ne pourra pas le gérer.

Je travaille actuellement sur un projet où il me faut résoudre ce problème et trouver une approche pour le gérer. J'ai pensé qu'il pourrait être utile aux autres de partager ma pensée ici. Et ce pourrait être un bon endroit pour obtenir des commentaires sur ma pensée.

Magasin de faits

C'est une assez bonne idée de développer des services afin qu'ils collectent des faits qui peuvent théoriquement être rejoués pour reproduire le même état dans tous les systèmes en aval affectés.

Par exemple, supposons que vous construisez un courtier de messages pour une plate-forme de négociation d'actions. ( J'ai déjà travaillé sur un projet comme celui-ci auparavant, c'était horrible, mais aussi une bonne expérience d'apprentissage.)

Supposons maintenant que les métiers entrent en jeu et que 3 systèmes s'y intéressent:

  1. Un ordinateur central de la vieille école qui doit rester à jour
  2. Un système qui rassemble toutes les transactions et les partage avec des partenaires sur un serveur FTP
  3. Le service qui enregistre la transaction et réattribue les actions au nouveau propriétaire

C'est un peu compliqué, je sais, mais l'idée est qu'un message (fait) entrant, a divers effets distribués en aval.

Imaginons maintenant que nous maintenions un magasin de faits, un enregistrement de toutes les transactions entrant dans notre courtier. Et que les 3 propriétaires de services en aval nous appellent pour nous dire qu'ils ont perdu toutes leurs données des 3 derniers jours. Le téléchargement FTP a 3 jours de retard, le mainframe a 3 jours de retard et tous les échanges ont 3 jours de retard.

Parce que nous avons le magasin de faits, nous pourrions théoriquement rejouer tous ces messages d'un certain temps à un certain temps. Dans notre exemple, ce serait il y a 3 jours jusqu'à maintenant. Et les services en aval pourraient être rattrapés.

Cet exemple peut sembler un peu exagéré, mais j'essaie de transmettre quelque chose de très particulier: les faits sont les choses importantes à garder à l'esprit, car c'est là que nous allons utiliser dans notre architecture pour lutter contre les doublons.

Comment le magasin de faits nous aide avec les messages en double

Si vous implémentez votre magasin de faits sur un niveau de persistance qui vous donne les parties CA du théorème CAP , la cohérence et la disponibilité, vous pouvez effectuer les opérations suivantes:

Dès qu'un message est reçu d'une file d'attente, vous vérifiez dans votre magasin de faits si vous avez déjà vu ce message auparavant, et si c'est le cas, s'il est verrouillé pour le moment et en attente. Dans mon cas, j'utiliserai MongoDB pour implémenter mon magasin de faits, car je suis très à l'aise avec cela, mais diverses autres technologies DB devraient être capables de gérer cela.

Si le fait n'existe pas encore, il est inséré dans le magasin de faits, avec un état en attente et un délai d'expiration du verrou. Cela devrait être fait en utilisant des opérations atomiques, car vous ne voulez pas que cela se produise deux fois! C'est là que vous assurez l'idempotence de votre service .

Heureux cas - arrive la plupart du temps

Lorsque le magasin de faits revient à votre service pour lui dire que le fait n'existait pas et qu'un verrou a été créé, le service tente de faire son travail. Une fois cela fait, il supprime le message SQS , et marque le fait comme terminé.

Message en double

C'est donc ce qui se passe lorsqu'un message arrive et que ce n'est pas un doublon. Mais regardons quand un message en double arrive. Le service le récupère et demande au magasin de faits de l'enregistrer avec un verrou. Le magasin de faits lui indique qu'il existe déjà et qu'il est verrouillé. Le service ignore le message et le saute! Une fois le traitement du message terminé, par l'autre travailleur, il supprimera ce message de la file d'attente et nous ne le reverrons plus.

Cas de catastrophe - arrive rarement

Alors, que se passe-t-il lorsqu'un service enregistre le fait pour la première fois dans le magasin, puis obtient un verrou pendant une certaine période, mais tombe? Eh bien, SQS vous présentera à nouveau un message, s'il a été récupéré, mais pas supprimé dans un certain délai après avoir été servi dans la file d'attente. C'est pourquoi nous codons notre magasin d'informations de sorte qu'un service conserve un verrou pendant une durée limitée. Parce que s'il tombe, nous voulons que SQS présente le message au service, ou une autre instance de celui-ci à une date ultérieure, permettant à ce service de supposer que le fait doit être incorporé à nouveau dans l'état (exécuté).

39
hendrikswan

Il n'existe aucun moyen au niveau de l'API d'empêcher la publication de messages en double dans une file d'attente SQS. Vous auriez besoin de gérer cela au niveau de l'application, je le crains.

Vous pouvez utiliser une table DynamoDB pour stocker vos noms de domaine en attente d'analyse et ne les ajouter à la file d'attente que s'ils ne sont pas dans DynamoDB par exemple.

4

Selon AWS Docs, Exactly-Once Processing fournit un moyen d'éviter les messages en double.

Contrairement aux files d'attente standard, les files d'attente FIFO n'introduisent pas de messages en double. FIFO vous aident à éviter d'envoyer des doublons à une file d'attente. Si vous réessayez l'action SendMessage dans le Intervalle de déduplication de 5 minutes, Amazon SQS n'introduit aucun doublon dans la file d'attente.

Si votre file d'attente est une file d'attente FIFO et a activé la duplication basée sur le contenu, cette fonction peut être utilisée pour éviter les messages en double pendant l'intervalle de déduplication. Pour plus d'informations, lisez ceci section et le lien ci-dessous.

https://docs.aws.Amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sqs-queues.html#cfn-sqs-queue-contentbaseddeduplication

3
Keet Sugathadasa

Comme vous ne pouvez pas empêcher SQS d'envoyer les messages en double, vous devez l'implémenter de votre côté. Une façon simple de le faire est d'utiliser les consommateurs idempotents d'Apache Camel, voir http://camel.Apache.org/idempotent-consumer.html

2
faermanj