5

Je suis en train de refactoriser un système analytique qui fera beaucoup de calculs, et j'ai besoin de quelques idées sur des conceptions architecturales possibles pour un problème de cohérence des données auquel je suis confronté.Conception architecturale pour la cohérence des données sur un système analytique distribué

architecture actuelle

J'ai un système de file d'attente, dans lequel les différentes applications demandant de créer des messages qui sont finalement consommés par les travailleurs.

Chaque « Demande App » se décompose un grand calcul en petits morceaux qui seront envoyés à la file d'attente et traitées par les travailleurs .

Lorsque toutes les pièces sont terminées, l'"Application qui demande" consolidera les résultats.

En outre, les travailleurs consomment des informations à partir d'une base de données centralisée (SQL Server) afin de traiter les demandes (Important: les travailleurs ne changent pas de données sur la base de données, n'ingèrent il).

Current Architecture

Problème

Ok. Jusqu'ici tout va bien. Le problème se pose lorsque nous incluons un service Web qui met à jour les informations sur la base de données. Cela peut arriver à n'importe quel moment, mais il est essentiel que chaque "grand calcul" provenant de la même "application demandant" voit les mêmes données sur la base de données.

Par exemple:

  1. App A génère des messages A1 et A2, en l'envoyant à la file d'attente
  2. travailleur W1 capte un message A1 pour le traitement.
  3. Le serveur Web met à jour la base de données en passant de l'état S0 à S1.
  4. travailleur W2 récupère un message A2 pour le traitement

Je ne peux pas juste ai travailleur W2 en utilisant l'état S1 de la base de données. pour que tout le calcul soit cohérent, il faut utiliser l'état S0 précédent.

Pensées

  1. Un motif de verrouillage pour empêcher le serveur Web de modifier la base de données alors qu'il ya une information consommation des travailleurs de celui-ci.

    • contre: Le verrou pourrait être sur pendant longtemps, puisque la forme de calcul différents "Demander Apps" peuvent se chevaucher (A1, B1, A2, B2, C1, B3, etc.).
  2. Créer nouvelle couche entre la base de données et les travailleurs (un serveur qui contrôle la mise en cache db par req app.)

    • contre: Ajout d'une autre couche peut imposer des frais généraux importants (peut-être?), et c'est beaucoup de travail, car je vais devoir réécrire la persistance des travailleurs (beaucoup de code).

Je suis en attente pour la deuxième solution, mais pas très confiant à ce sujet.

Des idées brillantes? Est-ce que je le conçois mal, ou manque quelque chose?

OBS:

  • Ceci est un énorme système existant 2 niveaux (en C#) que nous essayons de évoluer vers une solution plus évolutive avec un effort aussi minime que possible .
  • Chaque agent s'exécute potentiellement sur différents serveurs.
+1

Sonne énormément comme carte/réduire à moi. Pourquoi écrirais-tu une telle chose toi-même? Je voudrais juste utiliser Hadoop. – duffymo

+0

J'ai oublié de mentionner qu'il s'agit d'un énorme système hérité à deux niveaux (en C#) que nous essayons d'évoluer vers une solution plus évolutive avec le moins d'effort possible. Je crois que tout changer pour hadoop sera une tâche énorme. –

+0

Plus massif que l'écriture, le débogage et le maintien de ce que fait déjà Hadoop? Je serais sûr avant de commettre. – duffymo

Répondre

0

Merci à tous pour votre aide.

Puisque je crois que ce problème est courant dans d'autres scénarios, j'aimerais partager la solution que nous avons choisie.

En pensant plus en détail sur le problème, je l'ai compris pour ce qu'il est vraiment.

  • je besoin une sorte de contrôle de session pour chaque travail
  • Il y avait un cache en cours qui a servi de contrôle de session pour chaque travail

Maintenant, le calcul a évolué à distribuer, Je devais simplement faire évoluer mon cache pour qu'il soit également distribué. Pour ce faire, nous avons choisi d'utiliser une base de données en mémoire (hash-value), déployée en tant que serveur séparé. (dans ce cas Redis).

Maintenant, chaque fois que je commence un travail, je crée une pièce d'identité pour le travail et le transmettre à leurs messages

Lorsque chaque travailleur souhaite des informations de la base de données, il serait:

  1. Rechercher les données dans Redis (avec l'ID du travail)
  2. Si les données sont dans Redis, utilisez les données
  3. Si ce n'est pas le cas, chargez-le à partir de SQL et enregistrez-le dans redis (avec l'ID du travail).

À la fin du travail, j'efface tous les hachages associés à l'ID du travail.

1

Pouvez-vous versionner votre base de données?

Supposons que l'application demandeuse marque le début du calcul avec ct1. Maintenant, chaque message généré par ce calcul est marqué du même horodatage.

De plus, chaque mise à jour DB marque l'état de la base de données avec l'heure de la mise à jour. Donc l'état S0 est à l'instant t0, l'état S1 à t1 etc.

Maintenant, lorsqu'un travailleur reçoit un message, il doit obtenir l'état de la base de données où l'heure de mise à jour est la plus grande, plus petite ou égale à l'heure du message. Dans votre exemple, si A1 et A2 sont marqués avec ct1, et t1> ct1, les deux opérateurs récupéreront S0 et pas S1.

Cela signifie bien sûr que vous devez tenir plusieurs versions dans votre base de données. Vous pouvez nettoyer ces versions après un certain temps si vous savez que vos calculs doivent avoir fini après une certaine fenêtre temporelle.

+0

Vous avez un bon point. Je pourrais préparer chaque table pour permettre le versioning, bien que j'aie besoin de réécrire le schéma entier. Connaissez-vous une fonctionnalité dans Sql Server qui le ferait automatiquement ou au moins le rendrait plus facile? –

+0

Pas vraiment. Mais l'ajout de lignes d'horodatage à votre schéma de base de données ne devrait généralement pas être trop difficile. –

1

J'aime l'option 2, surtout si la quantité de données nécessaires pour l'ensemble des calculs n'est pas déraisonnablement grande. Je suppose qu'il existe un moyen de corréler (via ID) les calculs qui appartiennent au même travail global? Lorsque le premier message d'un ensemble de calculs arrive, le travailleur qui le récupère interroge la base de données et toutes les données nécessaires pour effectuer tous les calculs et crée un magasin de données temporaire. Ce que ce magasin de données ressemblerait dépend de beaucoup de facteurs (taille, structure, etc.), mais il pourrait s'agir d'un document blob /, d'un ensemble de données dans un schéma relationnel (isolé par correlationId), d'une entrée dans un cache d'entreprise, etc.

Vous devez faire attention au cas où Worker 1 et Worker 2 travaillent tous les deux sur le même ensemble de calculs, car un seul d'entre eux devrait créer le magasin de données, et les deux auraient besoin attendre que le magasin soit entièrement rempli avant de continuer.

+0

Je peux corréler les calculs au même travail global. Je peux générer un identifiant et le paramétrer pour tous les calculs. Mais découvrir toutes les données dont le travail aura besoin est une tâche très complexe pour moi.Je pensais ajouter un nouveau serveur à l'architecture que tous les travailleurs accèderont à la place de la base de données. ce serveur conservera un cache des résultats de la base de données par ID de travail. Qu'est-ce que tu penses ? –

+0

N'êtes-vous pas de retour au problème original, alors? Ou chaque calcul de la séquence ne repose-t-il que sur les résultats du calcul précédent? –

+0

chaque calcul est indépendant du résultat de l'autre, ils dépendent uniquement des données de la base de données. Ce "serveur" serait unique, agissant comme une façade pour toutes les connexions à la base de données, de sorte qu'il puisse gérer le cache de tout le monde en mémoire. Pas très confiant à ce sujet cependant. –

Questions connexes