web-dev-qa-db-fra.com

Pourquoi la base de données comme file d'attente est-elle si mauvaise?

Je viens de lire ceci article , et je suis confus.

Imaginons 1 webapp et 1 application distincte agissant comme "travailleur", les deux partageant la même base de données .

Oh, j'ai dit "partager" .. mais de quoi met en garde l'article? :

Quatrièmement, le partage d'une base de données entre des applications (ou services) est une mauvaise chose. Il est tout simplement trop tentant d'y mettre un état partagé amorphe et avant que vous ne le sachiez, vous aurez un monstre extrêmement couplé.

=> en désaccord. Dans certains cas, des applications distinctes font toujours partie de la même unité et, par conséquent, la notion de "problème de couplage" n'a aucun sens dans ce cas.

Continuons: la webapp gère les requêtes HTTP des clients et peut mettre à jour à tout moment certains agrégats (terme DDD), générant les événements de domaine correspondants.
L'objectif de l'ouvrier serait de gérer ces événements de domaine en traitant les travaux nécessaires.

Le point est:

Comment les données d'événements doivent-elles être transmises au travailleur?

La première solution, comme le promeut l'article lu, serait d'utiliser RabbitMQ, un excellent middleware orienté message.

Le workflow serait simple:

Chaque fois que le dyno Web génère un événement, il le publie via RabbitMQ, qui alimente le travailleur.
L'inconvénient serait que rien ne garantit la cohérence immédiate entre la validation de la mise à jour agrégée et la publication de l'événement, sans traiter les échecs d'envoi potentiels ... ou les problèmes matériels; c'est un autre problème majeur.

Exemple: Il serait possible qu'un événement soit publié sans succès de la mise à jour agrégée ... résultant en un événement représentant une fausse représentation du modèle de domaine.
Vous pourriez affirmer qu'il existe un XA global (validation en deux phases), mais ce n'est pas une solution qui convient à toutes les bases de données ou middlewares.

Alors, quelle pourrait être une bonne solution pour assurer cette cohérence immédiate? :
IMO, stockant l'événement dans la base de données, dans la même transaction locale que la mise à jour agrégée.
.

Mais pourquoi avoir besoin d'un programmateur supplémentaire côté webapp et d'ailleurs: pourquoi avoir besoin de RabbitMQ dans ce cas?

Par cette solution, il apparaît logiquement que le RabbitMQ pourrait être inutile, notamment parce que la base de données est partagée.
En effet, quel que soit le cas, nous avons vu que la cohérence immédiate implique une interrogation à partir de la base de données.
Ainsi, pourquoi le travailleur ne serait-il pas directement responsable de ce sondage?

Par conséquent, je me demande pourquoi tant d'articles sur le Web critiquent à peine la mise en file d'attente des bases de données, tout en faisant la promotion d'un middleware orienté message.

Extrait de l'article:

Simple, utilisez le bon outil pour le travail: ce scénario réclame un système de messagerie. Il résout tous les problèmes décrits ci-dessus; plus d'interrogation, remise efficace des messages, pas besoin d'effacer les messages terminés des files d'attente et pas d'état partagé.

Et une cohérence immédiate, ignorée?

Pour résumer, il semble vraiment que quel que soit le cas, c'est-à-dire partagé ou non, nous avons besoin d'interrogation de base de données .

Ai-je manqué quelques notions critiques?

Merci

34
Mik378

Si vous construisez une application simple à faible trafic, il y a quelque chose à dire sur le fait de garder un autre composant hors de votre système. Il est très probable que ne pas utiliser de bus de messages soit la bonne réponse pour vous. Cependant, je suggérerais de construire votre système de manière à échanger le système de file d'attente basé sur une base de données contre une solution middleware. Je suis d'accord avec l'article. Une base de données n'est pas le bon outil pour un système basé sur une file d'attente, mais cela peut être suffisant pour vous.

Les systèmes basés sur des files d'attente comme RabbitMq sont construits à grande échelle sur du matériel modéré. Leur architecture est en mesure d'y parvenir en évitant les processus qui rendent le système de base de données conforme ACIDE lent par sa nature. Étant donné qu'un bus de messages doit uniquement garantir qu'un message est stocké et traité avec succès, il n'a pas besoin de se soucier du verrouillage et de l'écriture des journaux de transactions. Ces deux concepts sont absolument nécessaires pour un système ACID, mais sont souvent une source de discorde.

En termes de performances, cela se résume à: vous avez une table SQL. Beaucoup de lectures et beaucoup d'écritures. Les deux nécessitent une sorte de verrouillage pour mettre à jour les lignes, les pages et les index. Votre mécanisme d'interrogation verrouille constamment un index pour effectuer des recherches dessus. Cela empêche les écritures de se produire; au mieux, ils sont en file d'attente. Le code effectuant le traitement se verrouille également pour mettre à jour l'état de la file d'attente au fur et à mesure de leur achèvement ou de leur échec. Oui, vous pouvez effectuer l'optimisation des requêtes après l'optimisation pour que cela fonctionne, ou vous pouvez utiliser un système spécialement conçu pour la charge de travail que vous demandez. Un RabbitMq mange ce type de charge de travail sans même transpirer; en plus de cela, vous pouvez enregistrer votre base de données de la charge de travail, ce qui lui donne plus d'espace pour évoluer en faisant d'autres choses.

Une autre chose à considérer est que la plupart des systèmes de files d'attente n'utilisent généralement pas de technique d'interrogation (certains autorisent HTTP, mais recommandent d'éviter d'utiliser pour le côté réception). RabbitMq utilise des protocoles réseau spécialement conçus pour les bus de messages tels que AMPQ .

Edit: Ajout d'un cas d'utilisation.

La façon dont j'ai utilisé Rabbit est que j'ai eu un point de terminaison API qui accepte un changement qui nécessite une table de base de données très utilisée. Ce tableau est constamment contesté et ne pourra pas parfois enregistrer une modification en temps opportun à partir de l'API. Ce que je fais à la place, c'est d'écrire la demande de changement dans une file d'attente, puis d'avoir un service qui gère ces messages comme ils le peuvent. Si un conflit de base de données se produit, la file d'attente augmente simplement et le traitement des messages est retardé. Le temps de traitement est généralement inférieur à 14 ms, mais en cas de conflit élevé, nous obtenons jusqu'à 2-3 secondes.

31
brianfeucht