Accueil Nos publications Blog NoSQL User Group – MongoDB

NoSQL User Group – MongoDB


La session du 26 juillet du NoSQL User Group a convié Antoine Girbal de la société 10gen pour nous faire une présentation générale de MongoDB.

Je vous propose donc un petit résumé afin d’introduire MongoDB à tous ceux qui ont manqué l’événement.

Une base NoSQL

MongoDB est une base de données NoSQL open source initiée par la société 10Gen.

Dans un premier temps, Antoine a explicité le terme NoSQL tel qu’il était vu dans MongoDB :

  • Pas de jointure
  • Pas de transactions
  • Pas de structure de données rigide
  • Un autre langage de requêtage que le SQL
  • Une scalabilité importante

Il distingue ensuite les RDMS (Relational Database Management System), qui possèdent de nombreuses fonctionnalités avancées pour répondre à un maximum de besoins, des bases de données clefs/valeurs axées sur la rapidité. MongoDB, qui est une base de données orientée documents, est un compromis entre les deux.

En effet MongoDB, offre des fonctions de requêtage avancées, des mises à jour partielles et atomiques des données ainsi que d’autres options permettant de choisir le bon compromis entre l’assurance que les données soient bien à jour sur les serveurs et la rapidité d’écriture.

Javascript et JSON

Après cette introduction, Antoine est entré dans le vif du sujet avec, dans un premier temps, l’explication de la manière dont étaient stockées les données puis ce qui était le fondement de MongoDB, à savoir, le format JSON.

Ainsi, par exemple, un article simple peut être représenté de la manière ci-dessous :


{
titre:"test",
auteur:"mathieu parisot",
comments: [
{auteur:"soatien1",text:"my comment"},
{auteur:"soatien2",text:"another comment"}
]
}

En fait, MongoDB utilise comme norme de stockage un dérivé binaire de JSON : le BSON qui offre un bon rapport entre la place occupée et la rapidité de parsing (notamment en y intégrant la taille de chaque entrée pour pouvoir passer à la suivante si la clef ne correspond pas).

En arrière plan, la base reste une base clef/valeur où la valeur est un document JSON complet. Cependant, contrairement aux bases purement clef/valeur, il est possible de requêter sur n’importe quel élément du document ou sous document (dans notre exemple, il peut s’agir de l’auteur de l’article ou d’un commentaire). La structure des données est totalement libre et il est possible de rajouter très facilement, par exemple, une date à notre article. Ainsi, il n’y a pas de notion de colonne à ajouter.

Enfin, les champs sont fortement typés.

La distribution des données

Suite à ces notions fondamentales, Antoine a détaillé la gestion des replicaset et des shards qui sont deux notions utilisées lors de la distribution des données entre plusieurs serveurs.

Les replicasets

En effet, un point primordial pour une solution NoSQL est sa capacité à scaler. Ainsi, il est possible, et fortement recommandé, de commencer directement avec 3 serveurs MongoDB dans un replicaset. Un serveur sera alors désigné comme étant le serveur principal (master) tandis que les autres seront dits secondaires (slave). Les données écrites sur le master sont automatiquement répliquées sur les slaves et, en cas de défaillance de ce dernier, un nouveau maître est élu.

Cette notion “d’élection” est importante et est vitale pour bien comprendre ce qui se passe en cas de perte d’un serveur maître. L’élection d’un nouveau maître, se fait à la majorité absolue. Par contre, si le nombre initial de serveurs est trop bas ou si une défaillance d’un grand nombre de serveurs se produit, il est possible que les serveurs restant n’arrivent pas à atteindre cette majorité : dans ce cas, le replicaset n’est plus accessible en écriture mais seulement en lecture.

Pour pallier à ce type de problèmes il est possible d’installer un serveur “arbitre” qui ne contient pas de données et dont le rôle est de trancher en cas d’élection impossible afin d’éviter que le replicaset cesse de fonctionner.

Les Shards

Le deuxième point primordial pour une solution NoSQL est sa rapidité (plusieurs milliers d’opérations par secondes). C’est dans ce contexte qu’intervient la notion de shards qui correspond à des groupes de replicaset. Chaque groupe contient une partie des données (par exemple, dans notre cas d’usage, tous les articles commençant par un A jusqu’à F, le suivant de F jusqu’à N, etc.).

Cela permet de répartir la charge entre les différents replicasets. Cette répartition est purement basée sur l’espace disque, il n’y a pas d’analyse de la charge CPU ou mémoire.  Afin d’être le moins intrusif possible, les replicasets ne savent pas qu’ils se trouvent dans un shard.

Ces serveurs ont également à leur charge la décision de distribution des données et de la répartition de la charge. Ces serveurs sont donc très légers et ne nécessitent pas nécessairement de machine dédiée.

Le routage se fait via un troisième type de serveur appelé MongoS qui contient une copie des tables de routage des serveurs de configuration et qui se charge d’envoyer les données au bon replicaset. Ce serveur est également très léger et est, le plus souvent, directement associé à chaque serveur applicatif qu’utilise l’application.

Ces problématiques de distributions sont relativement complexes et imposent de nombreuses contraintes sur la génération des identifiants, les temps de réponses en cas de requêtes sans index, etc.

Le requêtage

Enfin, Antoine a évoqué la manière de requêter les données. Ces dernières s’écrivent à l’aide de javascript et de JSON via un ensemble d’instructions spécifiques à MongoDB. D’ailleurs, il est intéressant de remarquer que l’outil en ligne de commande est, en fait, un interpréteur javascript.

Exemples de requêtes :


db.users.find({'auteur: 'mathieu parisot'})

db.users.find({}).sort({auteur: 1});

db.users.find().skip(20).limit(10);

Les mises à jour se font via la même syntaxe javascript/JSON :


myColl.update( { _id: X }, { _id: X, name: "Joe", age: 20 }, true );

db.people.update( { name:"Joe" }, { $inc: { n : 1 } } );

Tous les mots clefs précédés de $ sont les opérateurs MongoDB ($gt pour supérieur, $inc pour incrémenter, etc.)

Il est important de noter qu’il est indispensable de poser des indexes sur les champs utilisés dans les requêtes afin de garantir une bonne rapidité du système (surtout dans le cas de tris ou dans le cas où le système utilise les shards).

Et également…

Au fil des questions et de la présentation Antoine a également évoqué un certain nombre de sujets :

  • Map/Reduce : MongoDB supporte une version simple de Map/Reduce fortement optimisée dans la version 1.8 et encore davantage en 2.0
  • Il n’y pas pour le moment de système de recherche full text, il faut donc rajouter une solution externe type SolR.
  • MongoDB utilise le cache du système de fichier natif des OS, il prend donc autant de place en mémoire que nécessaire et il n’est pas possible de le limiter. Il est donc fortement recommandé de déployer MongoDB sur un serveur dédié : plus il y a de mémoire et plus les disques durs sont rapides, plus MongoDB sera performant.
  • Les documents sont limités à 16Mo, ce qui est largement suffisant pour stocker des données.
  • Pour stocker des documents il est recommandé d’utiliser GridFS qui est un système de fichier distribué.
  • Il existe des drivers pour de nombreux langages, ceux pour Java, DotNET et Ruby étant les plus avancés.
  • Il existe des systèmes ORM en Java : Spring Data et Morphia

Enfin un petit aperçu des entreprises utilisant MongoDB en production : Foursquare, Craiglist, MTV, Electronic Arts, bit.ly, SourceForge, etc.

Conclusion

Globalement, MongoDB à l’air d’être un très bon compromis entre la rapidité, la cohérence des données et la facilité d’utilisation. Reste la syntaxe qui lui est propre et le fait que la solution semble manquer un peu de maturité pour sortir du marché de niche, surtout sur les possibilités de recherche dans la base. Néanmoins, le fait qu’il y ait une entreprise derrière cette solution ainsi que son adoption croissante par de grosses structures semble promu à un bel avenir.