Une excellente journée à Rennes !

J’ai fait une conférence sur la prévalence aujourd’hui à Rennes, et c’était un vrai plaisir. Merci aux personnes qui sont venues, ont été attentives, bienveillantes et surtout ont posé autant de questions intéressantes. C’est un plaisir d’avoir un tel auditoire.

Bravo aussi aux organisateurs de l’évènement : la journée était parfaitement organisée, avec des orateurs de haut niveau mais très accessibles, et vous avez trouvé le positionnement idéal pour ne pas perdre les débutants tout en fournissant de la matière aux experts.

Retour sur ma session sur la prévalence

Je n’ai pas eu le temps de répondre à toutes les questions, et surtout, je me rends compte que je n’ai pas traité le sujet pour lequel il y a eu le plus de vite. Je m’en excuse platement : je me suis laissé embarqué dans le flux des questions et j’aurais du bloquer cinq minutes pour traiter cela en priorité.

Vous trouverez dans la catégorie Prévalence plus de détail sur la gestion de la modification du modèle de données, mais voici l’explication telle que je souhaitais vous la présenter lors de la conf’ :

Vous vous rappelez qu’on avait dans la classe BaseDonnees une liste de Personne, classe définie comme ceci :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DojoPrevalence
{
    public class Personne
    {
        private string _Nom;

        public string Nom
        {
            get { return _Nom; }
            set { _Nom = value; }
        }

        private string _Prenom;

        public string Prenom
        {
            get { return _Prenom; }
            set { _Prenom = value; }
        }

        public Personne(string Nom, string Prenom)
        {
            this._Nom = Nom;
            this._Prenom = Prenom;
        }
    }
}

Imaginons que nous ayons désormais besoin d’un membre GUID dans cette classe. Nous allons arrêter l’application prévalente, modifier la classe comme ci-dessous, recompiler et relancer :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DojoPrevalence
{
    public class Personne
    {
        private string _Nom;

        public string Nom
        {
            get { return _Nom; }
            set { _Nom = value; }
        }

        private string _Prenom;

        public string Prenom
        {
            get { return _Prenom; }
            set { _Prenom = value; }
        }

        private string _Guid;

        public string Guid
        {
            get { return _Guid; }
            set { _Guid = value; }
        }

        public Personne(string Nom, string Prenom)
        {
            this._Guid = System.Guid.NewGuid().ToString("N");
            this._Nom = Nom;
            this._Prenom = Prenom;
        }
    }
}

Que va faire le moteur de sérialisation ? Planter en nous disant que la classe a changé de définition ? Non, il va réagir le plus banalement possible en considérant que comme il n’a pas de donnée GUID, celle-ci sera simplement nulle. Du coup, les objets créés avant la modification du constructeur n’auront pas de GUID (ou plutôt, afficheront un texte par défaut), et ceux créés depuis la modification auront une valeur de GUID calculée.

Notez qu’on pourrait tout à fait décider de créer un GUID à la volée pour les anciens objets. Typiquement, ceci serait réalisé en mode lazy, lors de l’accès à la propriété.

Est-ce que ça marche aussi pour la suppression d’un champ ? Oui. La modification d’un nom de champ est vraiment un cas théorique car le plus simple est évidemment de créer un champ qui pointe sur un autre, mais imaginons que vous deviez transférer de la donnée d’un champ à un autre. Vous pouvez simplement faire une migration en deux étapes : création d’un nouveau champ qui se remplit à chaque appel, puis mise en place de la nouvelle version une fois toute la donnée migrée, pour supprimer éventuellement le champ qui ne sert plus.

A nouveau, vous pouvez tout à fait décider de travailler en mode lazy : la première fois qu’une fonction lit la nouvelle donnée, elle recopie l’ancienne, la supprime de l’ancien champ, et l’objet est migré. Mais vous pouvez également décider de lancer une phase de migration sur le démarrage du moteur de prévalence, avant même que celui-ci commence à traiter des commandes. Tout dépend de votre volumétrie et de vos besoins.

Un point sur la scalabilité

L’un d’entre vous m’a posé une question supplémentaire une heure plus tard sur la scalabilité et les moyens à mettre en oeuvre pour mettre en place des serveurs distribués utilisant la prévalence.

Je conseille de choisir entre deux architectures.

La première : gérer deux piles de commandes, et balancer la charge entre les serveurs par affinité de session avec les commandes affectées au serveur en mode prioritaire, et les commandes dupliquées pour synchronisation en mode à basse priorité. Cette méthode est adaptée à des mécanismes tels que de la gestion de demandes par internet (portails ouverts au grand public, etc.) où les risques de concurrence sur la donnée sont pour ainsi dire nuls. Et n’oubliez pas que le fait de ne pas avoir une consistance ACID ne signifie pas qu’on ne traite pas les cas restants, mais simplement qu’on accepte de les traiter dans un mode légèrement dégradé (mais qui en pratique ne pose pas de problème) afin de gagner en performance.

La seconde : vous avez un risque plus fréquent de concurrence sur la donnée, et il faudra mettre en place un système plus complexe, basé sur un mécanisme de compensation. Chaque serveur traite ses commandes, et les autres serveurs envoient des commandes de mise à jour des données (synchronisation du résultat au lieu de distribution des commandes sérialisées). Si les timestamp indiquent que la donnée a été modifiée entretemps, les serveurs émettent une commande de compensation permettant d’annuler les effets de toutes les commandes jusqu’à celle posant problème incluse. Evidemment, ceci augmentera fortement le temps de traitement de cet ensemble de commandes (il faudra repartir du dernier snapshot), mais c’est le prix à payer pour garder la consistance, et les cas, en pratique, sont ridiculement rares vu les vitesses de traitement de la donnée en mémoire. Cette architecture est plus particulièrement adaptée aux commandes nécessitant des traitements métier complexes.

Pour améliorer encore les performances de cette deuxième architecture, et ainsi créer une sorte d’hybride entre les deux systèmes profitant au mieux des avantages de chacun, il serait envisageable d’avoir un niveau de direction intelligent des commandes sur les serveurs en fonction de critères interdisant a priori la concurrence. C’est d’ailleurs ce qui est fait sans intervention sur la distribution lorsqu’on sépare les moteurs de prévalence sur des métiers différents.

La scalabilité profite à plein de la prévalence, par une sorte de double-effet kisscool : les transactions BASE plutôt qu’ACID favorise fortement la mise à l’échelle, mais en plus le fait d’avoir des traitements plus rapide, en plus d’améliorer les performances, améliore également la montée en charge des serveurs et diminue encore plus les risques de concurrence.

Conclusion

J’espère pouvoir vous montrer dans quelques semaines un premier prototype d’un convertisseur SQL –> requêteur intégré de prévalence, qui pourrait être un premier pas vers un connecteur ADO.NET pour les données prévalentes. Le résultat sera publié en Open Source, très certainement sur CodePlex. Gardez un œil sur ce blog si vous êtes intéressés !

Si d’autres questions vous viennent ou si vous souhaitez expérimenter la mise en place de la prévalence, surtout n’hésitez pas à me contacter par les commentaires. Et si vous avez loupé ma session, vous pouvez la retrouver à l’AgileTour Vannes le 14 Octobre, et à l’AgileTour Nantes le 21 du même mois.

About JP Gouigoux

Jean-Philippe Gouigoux est Architecte Logiciel, MVP Connected Systems Developer. Il intervient régulièrement à l'Université de Bretagne Sud ainsi qu'à l'Agile Tour. Plus de détails sur la page "Curriculum Vitae" de ce blog.
This entry was posted in .NET, C#, Prevalence, Retours and tagged . Bookmark the permalink.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha Captcha Reload