Dans le billet précédent nous avons passé en revue les tares majeures du SGBDR et les nuisances occasionnées à l'activité de développement. Nous allons maintenant étudier une solution qui non seulement résoud le problème de la persistance, mais simplifie dramatiquement le développement, les tests, le déploiement et l'exploitation.
J'ai déjà mentionné plusieurs fois l'architecture "LMAX"
. L'idée c'est qu'une application serveur reçoit des messages en entrée. Ces messages définissent une succession de changements d'états. Toutes les données "chaudes", c'est à dire l'état de l'application, résident entièrement en mémoire vive. Les messages sont traités séquentiellement donc de façon complètement déterministe. Comme il n'y a pas de concurrence d'accès il n'y a pas de verrouillage donc pas de commutation entre fils d'exécution et donc pas d'invalidation des caches du processeur (voir article précédent sur Netty). Comme la séquence de messages en entrée définit l'état de l'application, il suffit de persister les messages et de les rejouer pour restaurer un état antérieur. Ce modèle de conception s'appelle le "sourçage d'évènements" ("Event Sourcing"
).
Donc là en dix lignes on vient de pulvériser la notion même de SGBDR. On vient aussi de tripler (au moins) les performances de l'équipe de développement. J'explique.
--- Le code applicatif c'est du Java délivré de tous les compromis nécessaire à une projection objet-relationnel. Genre, les entités persistantes immuables et les collections de Guava pour pas un rond de plus.
--- On dégage tout le code pour faire rentrer les objets du code applicatif dans le SGBDR et on organise un pot de départ pour le consultant Hibernate. Le code de persistance qui écrit et lit les messages est le même que pour se parler sur le réseau.
--- Le code de migration des données est embarqué dans le code applicatif. Quand on persiste des messages, on persiste leur version de schéma. N'importe quelle version de l'application doit savoir lire tous les schémas antérieurs. Avantage : le code de migration s'écrit et se teste en pur Java.
--- Le code de requêtage c'est juste des parcours de listes d'objets en mémoire et on organise un pot de départ pour le consultant Oracle.
--- La modélisation applicative se fait en décrivant les messages en entrée et en sortie. On finance les pots de départ avec l'économie réalisée sur la license de PowerAMC.
--- Cette modélisation sous forme de messages se décline immédiatement en tests unitaires.
--- La séquence de messages est une piste d'audit au grain le plus fin. On peut la sauvegarder sur un système tiers (genre Amazon S3). Oui ça veut dire que l'application sait gérer ses propres sauvegardes, donc encore un pot de départ, cette fois pour l'administrateur système.
--- Comme le code applicatif est parfaitement séquentiel, il n'y a plus de problèmes de concurrence d'accès (plus de détails là-dessus très bientôt).
Sérieux, le sourçage d'événements c'est de la bombe. Il anéantit des problèmes majeurs qui plombent les développement basés sur des SGBDR. Tu vois ça tu te dis : "Non je peux pas c'est de la triche." Mais toute l'informatique c'est de la triche et donc ta paye aussi. Je sens que la triche ne va pas poser problème longtemps.
Bon il y a des questions qui se posent. Que se passe-t-il quand le journal devient trop gros ? Deux cas de figure.
Déjà il se peut que ça n'arrive jamais parce que l'application remet périodiquement la plupart des données à zéro, par exemple en début de journée. Les données chaudes peuvent devenir froides, c'est à dire qu'on les historise. Est-ce que ça ne va pas nous faire retomber dans le problème d'avant ? Mais on a vu avec l'exemple du modèle en étoile que les problèmes disparaissaient quand on s'abstenait de toute mise à jour ou suppression. Si le type de données s'y prête on peut utiliser une base documentaire comme Lucene et bénéficier de ses impressionnantes capacités d'indexation. On peut aussi ressortir un SGBDR juste pour me faire enrager.
Si le journal dépasse une certaine taille, on peut le compresser en prenant un instantané de l'état, puis en l'incluant au début d'un nouveau journal (git et Prevayler font déjà ça).
Lors d'une reprise sur panne, il faut que le rejeu du journal s'effectue assez rapidement. Mais comme la logique applicative ne comporte pas d'entrées-sorties c'est normalement le cas. Pour certains calculs coûteux on déclenche un traitement asynchrone dont seul le résultat sera journalisé.
Bien sûr le sourçage d'événements ne convient pas pour tout. Maintenant un petit exercice.
Considérons toutes les applications d'informatique de gestion qu'on connaît. Combien satisfont les critères suivants :
- Toutes les données chaudes tiennent dans le tas d'une JVM.
- Un seul serveur absorbe toute la charge, considérant qu'on peut consommer la totalité de son temps processeur.
Si on compte toutes les applications d'informatique de gestion utilisées en interne, je dirais au moins la moitié, peut-être les trois quarts. Il y a des applications qui traitent des volumes importants mais dont les données cessent très vite d'être chaudes. Il y a des applications qui nécessitent des serveurs en grappe parce qu'on n'arrive pas à utiliser plus de `15 %` de leur processeur. Donc là je ne sais pas pour qui c'est une bonne nouvelle, mais je viens d'amputer les vendeurs de SGBDR de la moitié de leur revenus (c'est pas tout à fait vrai dans la mesure où les gros trucs sont facturés plus cher).
Une autre question toute simple : s'il y a un seul serveur, que se passe-t-il en cas de panne ? C'est une question de budget.
Si on est riche on met en place une solution de réplication basée sur la garantie de l'unicité d'un dirigeant au sein d'un groupe de serveur. Ça se fait grâce aux protocoles Paxos ou "Raft"
, qui garantissant que tous les membres d'un groupe voient bien le même état. Je n'ai étudié que Raft, qui est conçu pour être plus simple que Paxos. Comme Raft est basé sur un journal d'événements, il y a une compatibilité fondamentale avec le modèle du sourçage d'événements. Notons que la réplication de journal est le grand classique des systèmes distribués puisque c'est là-dessus que se basent git ou la Blockchain.
Je ne veux pas m'étendre maintenant sur cette histoire de journal répliqué en temps réel vu que ça mérite un livre entier. Tout ce qu'il faut retenir c'est que le sujet demeure hors de portée du grand public ; heureusement il y a moyen de se rabattre sur une solution de type "DRBD"
, qui réplique une partition sur une machine distante (ou plusieurs).
Dans le prochain épisode nous verrons plus en détail le cycle de vie du journal.