Il y a quelques temps, lorsqu'un projet informatique démarrait, une question d'architecture qui se posait systématiquement, était "quelle base de données (relationnelle) utilisons-nous ?", et la subsidiaire (en langage objet), "quel mapping relationnel/objet ?". La réponse était d'ailleurs souvent "hibernate/mysql" dans le monde java.

Le mouvement NoSQL est issu d'un besoin de stockage de données important, scalable, performant, et robuste sans avoir toutes les fonctionnalités d'une base relationnelle. Ces besoins ont été ceux de gros sites comme google, facebook, twitter, amazon, linkedin, sourceforge, github...

Si certains discours ont été excessifs au départ (comme souvent lors d'une inversion de tendance), c'est en réaction à des années de domination du monde relationnel dans le domaine de la persistance, et aux difficultés des développeurs à s'interfacer avec ces systèmes. A présent beaucoup de produits ont été développés offrant de réelles alternatives au monde des SGBDR :


Et les autres types de bases qui existaient avant le mouvement NoSQL comme bases objets (Versant, Objectivity), les bases XML (eXist, Qizx), qui bénéficieront peut-être d'un regain d'intérêt. Tant mieux. Au sujet des précurseurs, nous pouvons citer d'ailleurs BerkeleyDB (1986), base clé-valeur utilisée sur un nombre de projet impressionnant, et mnésia, base de tuples/records erlang.

Grâce à ce mouvement, aux nouveaux produits, aux besoins des sites internet de gros volume, au delà du mouvement NoSQL, une nouvelle vision du stockage des données apparaît : c'est le fractionnement des modes de stockage vers une persistance aux formes multiples. La programmation polyglotte représentait le choix du meilleur langage en fonction du besoin, nous avions vu cela par exemple à la Qcon en 2010. La persistance polymorphe, consiste à choisir le meilleur moyen de stockage de données en fonction de son usage, et d'en avoir éventuellement plusieurs pour un seul module applicatif.

Par exemple twitter a créé un module de chargement de page web pour les urls présentes dans les tweets. Appelé SpiderDuck, il utilise HBFS construit sur Hadoop, lui-même fondé sur Hbase, et Cassandra. HBFS sert à stocker les informations récupérées sur les sites pointés par les url. Cassandra sert à stocker les métadonnées des url. A noter également qu'ils utilisent memcached (qui est une structure de données clé/valeur en mémoire), pour cacher les fichiers robots.txt des sites.

D'autres fonctions d'une application paraissent assez proches des modèles proposés par ces bases. Par exemple :

  • Redis pour le stockage de paramètres de session pour ses performances, sa simplicité et le format adapté clé/valeur
  • MongoDB pour l'aggrégation de logs car il fait du sharding (partitionnement de données par enregistrement pour les répartir sur plusieurs serveurs). Également pour le stockage de modèle (au sens MVC) en Json
  • Neo4j pour stocker des données sociales (ex facebook avec les graphes par "amis")
  • Riak pour stocker un grand nombre de données sensibles avec réplication sur plusieurs noeuds (cf la notion de Eventually Consistent)

Cette multiplicité technologique a un coût en complexité, comme l'introduction de plusieurs langages dans un projet. Martin Fowler l'évoque dans Polyglot Persistence, un très bon article sur le sujet. Mais cet investissement sera remboursé par l'intégration plus aisée de ces bases avec le code, la scalabilité horizontale des données, la performance, et les possibilités offertes en terme de découplage entre différentes parties du code.

Récemment nous avons travaillé sur la séparation de nos binaires et de nos configurations. Nous avons cherché comment stocker les paramètres extrinsèques de nos applications (ceux qui sont gérés par les opés: urls, nom d'hôtes, ports, etc.). Nous avons exploré plusieurs possibilités (fichiers sous git, cassandra, mongodb). Nous n'avons pas encore fait le choix, mais il est peu probable que nous utilisions au final notre base mysql. En effet, le mode relationnel est assez éloigné de l'état actuel des paramètres qui sont en fichiers properties. Et puis la gestion de l'historique de nos paramètres est à faire par programmation avec ce mode de stockage (alors que certaines bases apportent cette fonction en natif).

Nous avons testé MongoDB qui permet de stocker du json avec plusieurs clés (en javascript) :

db.configurations.insert({
     env: "itg",
     version: "1.0.9",
     appli: "pse",
     params: {"param1":"valeur1", "param2": "valeur2"}
});

et faire des requêtes :

db.configurations.find({'env': 'itg'});

Autre solution que nous avons exploré, c'est Redis pour conserver des structures de données comme des listes, des sets triés, etc. Nous évitons ainsi le mapping qui existait entre les paradigmes du monde des langages de programmation et du monde relationnel. Retrouvez une courte introduction à Redis sur barreverte.

C'est donc de nouvelles perspectives qui sont ouvertes. Il ne s'agit pas de mettre les bases relationnelles au rebut, mais de les utiliser pour des données "froides", dont les accès sont peu fréquents ; ou encore pour des données structurées, conservées sur une durée importante, et dont nous ne connaissons pas l'usage, comme le reporting, les données décisionnelles, juridiques, financières.

La prochaine fois que vous avez besoin de données persistantes, à vos explorations et prototypes, utilisez la meilleure base pour votre environnement (langage de programmation utilisé, structures à stocker, expressivité et souplesse offerte par le langage de requête, utilisation d'index, architecture plateforme, etc.) ! Nous essayerons de parler plus précisément de ce sujet sur ce blog.