Rappelons la définition d’une présentation excellente : session où tu passes une heure à écouter et à recevoir l’enthousiasme des speakers, où tu sors de la salle en te disant : « Oh my god »… Et là, c’était vraiment une bonne session comme j’en vois pas souvent.
Fotopedia en quelques mots
Pierre Baillet (@octplane sur Twitter) est DevOps chez Fotopedia. Dev ET Ops. Un gars qui code ET qui pilote une plateforme qui fait plusieurs milliers de visites par jour.
Fotopedia est un site créé par Jean-Marie Hullot, un ancien d’Apple. Et pas n’importe lequel ancien employé d’Apple. Passé par NeXSTEP, vous avez peut-être lu le nom de Jean-Marie Hullot dans la bio de Steve Jobs. Avec une équipe, il a travaillé sur le projet de l’iPhone en secret à Paris.
Fotopedia est un site et un service qui permet de créer une encyclopédie de photos en haute qualité, sur le modèle de Wikipedia. Vous allez à un endroit, vous prenez des photos. Les photos sont sur Fotopedia. C’est simple et c’est génial. Le service est proposé sur iPad, sur les tablettes Androids, sous la forme d’un client lourd et enfin d’un site Internet.
Pierre explique que le site tourne 24h/24, sans aucun temps d’arrêt. MongoDB est une solution qui remplace petit à petit MySQL, car c’est tous simplement un système génial. Il permet de ne travailler que sur de petits exports de données, de faire des réplications, de travailler de manière asynchrone… Bref il a aussi révolutionné les méthodes de développements.
Deuxième contrainte : la scalabilité. Comment s’assurer que la solution pourra continuer à grandir ? Comment gérer le volume de données dans les mois, ou les années qui viennent ? Autant de challenges techniques à relever.
Fotopedia a été créé en 2006, avec aujourd’hui un bureau dans la Valley et un centre de R&D à Paris. Il y a 20 personnes, quelques anciens d’Apple, mais surtout des développeurs passionnés.
Fotopedia c’est un mélange de FlickR et de Wikipedia. C’est aussi une volonté humaniste, en créant des catalogues de photos libre de droits, pour l’humanité. L’Unesco et les équipes de Fotopedia ont développé « Fotopedia Heritage« , une application avec 25 000 photos et 4 000 POI, téléchargeable gratuitement. En 2011, l’équipe a remporté aussi un Crunchies Award pour la meilleur application sur Tablet.
Fotopedia c’est 150 millions de photos vues par mois sur le site et via les différentes applications. Il y a une base MySQL, qui est voie de disparition, mais surtout 4 serveurs indépendants avec à chaque fois 4 bases MongoDB. Tout est hébergé chez Amazon Web Service. Cela représente environ 500 Gb de données structurées, pour ce qui est de la partie MongoDB uniquement.
Un site qui ne peut pas s’arrêter
Le site tourne en permanence, avec donc une particularité intéressante : on ne peut pas l’arrêter. La nuit ne peut qu’empirer mille fois les choses comme dit Roméo à Juliette. Et c’est donc souvent la nuit, que les équipes en France doivent gérer les quelques rares petits soucis. A chaque seconde, il y a entre 400 et 1000 connexions, selon les heures de la journée. Il y a eu par exemple plus de 100 000 téléchargements par jour des applications fotopedia les jours de pointes, autant dire que cela tourne plutôt bien.
Pierre explique qu’il y a d’une part le site web, qui peut avoir quelques instants d’indisponibilités, mais surtout 7 applications différentes sur iOS. Et les gens payent pour ces applications. Autant dire qu’elles doivent marcher, qu’il n’est pas possible qu’elles ne fonctionnent pas car un abruti d’admin système a confondu une prise électrique dans un data-center à Evry.
Lorsqu’il y a cependant des problèmes techniques, toute l’architecture du site est pensée pour que le service se dégrade progressivement. Un paquet de Varnish en frontal permettent de donner quelques dizaines de minutes avant que le site soit vraiment down. Le simple fait d’arrêter le système une dizaine de secondes génère une centaine d’erreurs. Bref, pas un truc de mickey.
Une mise en production chaque semaine, plusieurs fixes par jour
La mise en production est intéressante. Un DSI de base ne pourrait pas comprendre. Englué dans sa méthode à Gilles(!!) de mise en production, il lui faut souvent 2 semaines pour mettre en production sa bouse. Alors qu’ici, des mises en production, il y en a toutes les semaines.
Les équipes utilisent Git, avec plusieurs branches. Chaque mercredi, la branche de dev est poussée en production. Il y a ensuite 3 hotfixes par jour. Parfois 0, parfois 10 hotfixes. Tout le monde a le droit de pousser en production. Si tu casses quelque chose, tu répares. Si tu ne sais pas réparer, tu te casses. Logique.
Les migrations de données doivent donc être transparents. Pierre reviendra plus tard sur l’utilisation et les avantages de MongoDB, qui me fait de plus en plus penser à la différence d’approche entre SVN et Git. Une fois que tu as compris que Git te permet de travailler de manière asynchrone à ton rythme, tu as compris Git. Et bien MongoDB permet aussi de ne travailler que sur des petits subsets de ses données, de faire des dumps sur S3 et de remonter en local les données. More on this later, stay tuned.
Côté infrastructure et surtout framework Web, c’est du Ruby On Rails. Mais bon, de la bouche de Pierre, ça rame. Alors pour que le truc tienne la charge, il faut lui coller un certain nombre de machins comme HAProxy, NGinx, Unicorn Rack HTTP, mongo-resque et d’autres noms de médicaments non remboursés par la Sécurité Sociale…
Côté langages, il y a du Java, du Scala, mais surtout du Ruby. L’équipe travaille sur d’autres solutions, pour avoir de meilleurs performances. Scala est à l’étude en ce moment, mais pour la partie backend. Ruby on Rails reste et restera le framework Web pour l’instant, car il est bien maîtrisé par les équipes. Les premières versions du site utilisaient MySQL, avant que MongoDB ne soit ajouté. Il reste encore aujourd’hui 13 tables. L’objectif est de virer MySQL et de ne garder que MongoDB.
2 ans d’expérience opérationnelles sur MongoDB
L’équipe est plutôt rodée à MongoDB, puisqu’elle l’utilise depuis septembre 2009 en production. Plus de 70% des données de Fotopedia sont stockées sur MongoDB.
Pour le monitoring en production, Pierre cite Munin et surtout Nagios. MongoDB est utilisé aussi pour collecter les logs de l’application. En frontal, ils utilisent Scribe, une solution de Facebook, qui permet de recevoir en temps réel les logs applicatifs, et de les stocker. Scribe est codé en C++ avec des I/O non-bloquantes.
MongoDB est aussi utilisé pour stocker toutes les erreurs, les transactions lentes, bref tout ce qui va mal. Le log d’erreur est limité en taille. 1Go de messages d’erreur, c’est une heure sur le site… Il n’est pas possible de tout loguer.
L’hébergement est à 100% sur AWS. Pierre explique que les machines ne sont pas très fiables. De temps en temps, il faut déplacer rapidement une partie de l’application car Amazon signale un risque d’incident. Il faut alors utiliser des scripts pour recréer une instance en quelques minutes, avant le crash. Grâce à des systèmes de surveillance et de redondances, ce type d’opération arrive cependant rarement.
Côté espace disque, ils sont abondants. Les disques montés sur Amazon sont assez lents. Pour certains traitements non critiques, où vous pouvez accepter de perdre des données de travail, les disques locaux sont plus performants. Les disques locaux sont plus pratique que les EBS (Elastic Bloc Storage).
Pour la base MySQL, ils utilisent AWS RDS. Pas cher et facile à configurer.
Comme le business n’est pas critique (vous n’essayez pas de faire un achat), il est possible de perdre un client en cas de plantage. Vous allez vous retrouvez avec une page d’erreur, vous rechargerez votre page, et vous pourrez continuer votre navigation. Tout le site est pensé en asynchrone, sans session.
Utilisation quotidienne de MongoDB
Tout d’abord c’est un excellent outil pour les développeurs. Vous pouvez configurer un serveur MongoDB en local avec une partie des données, commencer à travailler, tout est simple à configurer. En tant que développeur, Pierre explique que lorsque vous passez à MongoDB, votre modèle change beaucoup. Il observe que souvent, on remplace 2 ou 3 tables de base de données relationnelles, par un seul catalogue MongoDB. Tout est vraiment orienté développeur. Le code est plus facile à lire, et finalement, l’application devient plus robuste. En effet, comme il n’y a pas la notion de relation ou de jointure, finalement votre application est codée/pensée pour gérer des objets détachés, sans relation. Tout le code devient défensif.
Vous avez une entité Client avec la notion de Pays… disons que vous n’exportez qu’une partie de la base Client… et bien imaginez que votre code va traiter le fait que le Pays n’est pas présent. Peut-être qu’un simple champ blanc sera affiché sur la page web… ou que votre application plantera…
Ecrire et travailler avec mongoDB c’est donc moins de tables, et moins de requêtes. Le développeur remonte en une seule fois ce dont il a besoin. Pas de problèmes de jointures ou de requêtes en cascade.
Un autre point intéressant, c’est l’évolution du schéma. Si vous avez une base MySQL et que vous devez passer un script ALTER, croyez Pierre sur parole : vous allez boire des cafés. De leur expérience, cela ne marche pas correctement avec MySQL. Il faut arrêter le service, croiser les doigts et attendre que le script passe… ou pas. Parfois même, cela donne des trucs assez moches, surtout si vous utilisez un ORM. Qui n’a jamais réutilisé un champ de la base car il ne pouvait pas toucher au schéma ?
Avec MongoDB, vous avez la liberté de changer le schéma. Après vous avez un cerveau, et vous n’allez pas faire n’importe quoi toutes les 5 minutes. Sinon vous avez un autre problème. Vous êtes intelligent, vous allez ajouter ou changer quelques champs sur votre document. Pas plus. Il faut donc être organisé et réfléchir à son domaine. Mais comme vous êtes un dieu de l’approche Domain Driven Design, pas de soucis pour vous.
Pour que cela fonctionne correctement, vous comprenez bien qu’il faut avoir une architecture particulièrement bien pensée. La couche de présentation est programmée pour dégrader et gérer l’absence de valeurs pour un champ. Ceci permet de continuer un service dégradé pour des parties non-critiques de l’application. Cela facilite aussi les tests et le développement en local. Et bien oui : votre application n’a pas besoin d’un état et d’un modèle complet pour fonctionner.
Lorsque les données doivent être migrées, comme lorsque vous décidez de réorganiser vos champs, il est assez facile de faire des batchs en Ruby sur MongoDB. Cela ne pénalise pas trop les performances. Vous laissez bien entendu le serveur tourner. Un concept simple qui rend inutile les stratégies de migration de cow-boy d’un DBA classique.
Il faut que le code soit prévu pour que la gestion des clés étrangères soit correctement pensé. Typiquement tout le code est défensif. Un développeur peut alors travailler sur un petit subset des données. De toutes les façons il est impossible de monter toutes les données sur le poste de travail d’un développeur. Lorsqu’il faut passer sur les données pour travailler, il faut que cela soit efficace et rapide.
Sur MySQL lorsque tu créés un index cela bloque la table. Sur MongoDB, cela ralentit mais on peut continuer à l’interroger en tâche de fond.
Faites-vous des sauvegardes sur disquettes ?
Du côté sauvegarde et restauration : MongoDB est livré avec des outils pour backuper facilement à la collection prês, plutôt que de travailler sur toute la base, qui n’est pas intéressant. Stockage sur S3, on peut ensuite remonter localement une partie des collections. MySQL avec ses FK c’est quasi impossible. Avec MongoDB on peut remonter une partie de la base, ce qui est très pratique et très simple.
Cela permet au développeur de travailler facilement sur des copies de la production.
Du code, du code et du code
MongoDB a un noyau assez petit. Peut-être 150 000 lignes de C++. Il se compile sans soucis sur des distributions modernes de Linux. 10gen fait des packages par distribution. Il existe des drivers pour la plupart des langages. Les drivers sont maintenus par 10gen.
Du côté Java, le driver n’est pas trop mal codé. Mais ses réglages par défaut ne sont pas optimum pour de la production. Cependant il est facile de trouver des ressources sur Internet, ce n’est pas du tout compliqué.
Du côté de Ruby, le driver de base avait un énorme trou de sécurité. Lorsqu’un client envoyait une requête à un serveur MongoDB, le driver ne vérifiait pas dans les premières versions le corelationID, le numéro de séquence. Et cela donnait des bugs en production assez difficile à identifier. Le souci a vite été réglé, et vu le nombre de projets qui utilisent MongoDB, tout ce qui est sécurité est plutôt bien géré.
Quelques mots sur la configuration en Cluster
L’infrastructure de fotopedia est intéressante. 4 Machines avec à chaque fois, 4 serveurs MongoDB sur chaque machine. Si j’ai bien compris, une machine est primaire, les 3 autres sont secondaires. Pour que MongoDB puisse fonctionner, il faut au moins 3 serveurs (pas forcément 3 machines). Chaque machine a 15 Go de mémoire, bref de quoi tenir la charge quotidienne. Si un serveur secondaire est trop en retard par rapport au serveur primaire, il s’arrête, se vide, et se resynchronise ensuite avec le primaire. Tout est automatique, c’est le principe même de MongoDB.
La configuration d’un cluster est vraiment facile avec MongoDB. Vous pouvez ajouter/retirer à la volée des serveurs, vous pouvez donner des poids, bref faire un vrai travail d’architecte. Si vous voulez avoir un backup, vous pouvez avoir un serveur qui reste tout le temps secondaire. Par exemple une machine avec des disques en Raid10, qui devient, de fait, un serveur de secours.
Côté client, le driver est conscient de la topologie du réseau, ce qui permet de donner de bonnes performances. En terme de haute-dispo, un primaire peut laisser la main à un autre serveur primaire. Il est important de comprendre que MongoDB est défensif. Si un noeud a 50%-50% (2 serveurs) il n’y a pas d’élections, les 2 machines passent en secondaire. Lorsqu’un serveur est en secondaire, il continue à servir les données. Mais il n’accepte pas les écritures. Cela pour éviter d’avoir 2 Masters, et donc 2 écritures de l’application sur 2 machines. C’est pensé si 2 sites perdent la connexion, et ne peuvent plus se voir. Il faut alors une troisième machine pour pouvoir effectuer une élection. Probleme du Split-brain.
Les compromis
Il faut entre 20 et 25 secondes pour ré-élire un master. Pendant ce temps-là, oui il y a un risque de plantage, mais finalement uniquement pour les clients Webs qui inter-agissent avec le site. Pour relativier, on parle d’un site d’images comme dit Pierre. Pas d’un site qui doit sauver le monde ou gérer des essais nucléaires en Iran.
En conclusion
MongoDB est un outil bien adapté aux équipes DevOPS. C’est un outil pour les développeurs qui permet de faire des choix plus tard, bien plus tard qu’avec une base relationnelle. Comprenez bien une chose : l’outil permet de ne pas décider au jour 1 de l’ensemble de votre modèle, et a été pensé pour s’adapter. Forcément, vous n’avez pas de modèles relationnels contraints par la base. L’application se charge de la cohérence et des relations entre les entités. Pierre rappelle que le code est plus simple, et que souvent vous retirez des tables de bases de données lorsque vous passez vers MongoDB.
Pour ma part, j’espère que vous pourrez voir cette présentation à Devoxx France en avril prochain. Les équipes de MongoDB vont aussi soumettre des sujets pour Devoxx France, en Anglais.
Enfin pour terminer, un grand merci à Xebia France pour cette superbe journée !
Quelques contre-arguments
Pour contre-balancer peut-être la présentation, nous pouvons relativiser en disant que Facebook tourne plutôt bien en production avec MySQL[1]. FourSquare a eu un souci avec MongoDB en 2010, comme aussi sans doute d’autres entreprises en ont eu avec MySQL, avec Oracle, avec une multi-prise dans un data-center à Evry…
On trouvera facilement un article d’un gars déçu par MongoDB ou surtout le fameux post sur Pastebin.com dont la véracité a été mise en doute. Vous trouverez d’ailleurs plus d’informations et les réponses de 10gen sur le poste original sur HackerNews.
Bref ne faites pas comme moi, ne soyez pas trop enthousiaste, testez, testez et re-testez. Mais ce retour d’expérience était vraiment riche et intéressant.
[1] http://www.datacenterknowledge.com/archives/2008/04/23/facebook-now-running-10000-web-servers/
Les slides de la présentation :
« Facebook tourne plutôt bien en production avec MySQL » et Twitter aussi, d’ailleurs, c’est absolument vrai…. Mais aussi parce qu’ils peuvent se payer une petite armée d’excellents dba mysql.
Mozilla avait aussi une ferme de mysql, avec plusieurs DBA. Ils ont viré leur base (mysql je crois), mis du NoSQL à la place (TokyoTyrant ou Ryak?) et du coup ils n’ont plus eu besoin de tous ces admins.
Dans une petite/moyenne structure, on peut aussi prendre en compte la complexité de la maintenance des outils. C’est aussi ce qui peut faire préférer elasticsearch à solr. Ou préférer d’autres solutions de map/reduce à Hadoop
Ca m’a fait marrer, il y a quelques mois, quand j’ai lu en diagonale, dans Géo, un reportage sur la Californie, « là où est né l’iPhone » comme l’écrivait ce magazine. Car j’avais lu auparavant l’article « Ce Français qui a inspiré l’iPhone » de L’Express: http://www.lexpress.fr/actualite/high-tech/ce-francais-qui-a-inspire-l-iphone_841728.html
La cellule « fantôme », qui avait pour vocation de préparer Apple au monde du mobile, était localisée à Paris.
L’architecture MongoDB me fait penser que, parmi toutes les bases NoSQL, MongoDB est sans doute celle qui ressemble le plus, en termes d’archi cluster, à une base SQL. Par ex, on retrouve des noeuds maitre et des noeuds secondaires, comme on peut en avoir quand on fait du clustering avec une base SQL.
De ce point de vue, une des bases qui s’éloigne le plus des bases relationnelles, c’est, par ex, la base Cassandra où tous les noeuds sont symétriques.
Alors qu’avec MongoDB, on a :
– des replica set, avec un noeud maitre + N noeuds secondaires (au moins 3 en tout: N+1 >= 3), accompagné, dans certains cas (?), d’un noeud ‘arbiter’ pour l’élection d’un noeud maitre (cas, je crois, où le nombre de noeuds dans un replica set est pair – hein ?)
– des noeuds config servers pour gérer la configuration du cluster (au moins 3 en tout)
– des noeuds mongos pour faire l’intermédiaire entre les clients et le cluster.
« Si un serveur secondaire est trop en retard par rapport au serveur primaire, il s’arrête, se vide, et se resynchronise ensuite avec le primaire »
Hum, dans ce cas, si le serveur secondaire est trop en retard, comment va-t-il rattraper son retard s’il s’arrête, se vide, et se resynchronise ensuite avec le primaire ? on ne rattrape pas son retard en s’arrêtant pour se vider, non ?
« Si un noeud a 50%-50% (2 serveurs) il n’y a pas d’élections, les 2 machines passent en secondaire »
donc, si on a 3 serveurs, 1 maitre + 2 secondaires, si on perd le maitre, les secondaires restent secondaires à tout jamais, non ?
et plus aucun update n’est accepté…
sauf si une nouvelle machine est rajoutée.
« Pierre rappelle que le code est plus simple, et que souvent vous retirez des tables de bases de données lorsque vous passez vers MongoDB »
oui, car NoSQL implique dénormalisation (car NoSQL ~ NoJoin), et donc, le modèle de la base se rapproche du modèle objet.
reste que dénormalisation peut impliquer aussi de multiples updates lors d’une mise à jour. Et se pose alors la question de la cohérence des donneés, pb qui se posait moins (voire, pas du tout) avec une base SQL.
« Il faut entre 20 et 25 secondes pour ré-élire un master. »
je ne comprends pas qu’il faille autant de temps.
cela me parait bizarre, sachant que, dans un replica set, les serveurs se connaissent déjà.
« On trouvera facilement un article d’un gars déçu par MongoDB »
perso, j’ai trouvé 2-3 articles qui pestaient contre MongoDB, et notamment sa gestion du clustering, et/ou ses performances qui chutaient quand les données ne tenaient plus totalement en RAM.
donc, je suis d’accord avec la conclusion: « testez, testez et re-testez » 😉
Nous utilisons également MongoDB en production depuis la v1 …
Si vous voulez avoir une base de données MongoDB en ligne, vous pouvez en créer une sur http://mongood.com
Nous avons 4 serveurs en replica_set… pour le moment il n’y a pas trop de limitation en phase beta.
Attention, passer à MongoDB rend tout retour vers MySQL très difficile … je me fait moi même souffrance sur des vieux projets MySQL !!
* Comme je le disais précédemment, MongoDB me semble la base NoSQL la plus proche des bases relationelles:
– définition de collections à la place des tables
– possibilité de définir des index
– mise à disposition d’un explain plan
– clustering master/secondary
– bien meilleures perfs en lecture qu’en écriture avec le write lock de MongoDB (et chute des perfs quand les données ne tiennent plus seulement en RAM)
* Maintenant, les bases SQL évoluent elles aussi, et tendent à devenir plus dynamiques/flexibles.
Par ex, dans MariaDB 5.3 – http://kb.askmonty.org/en/what-is-mariadb-53 – apparaissent les Dynamic columns : http://kb.askmonty.org/en/dynamic-columns
« Dynamic columns allows you to have a different set of « virtual columns » for each row in your table. You can at any time add or remove columns from a row. »
http://www.odbms.org/blog/2011/09/mariadb-the-new-mysql-interview-with-michael-monty-widenius/
Bref, les bases NoSQL poussent les bases SQL à évoluer et c’est tant mieux.
* voici qques retours d’expérience que j’ai lu à propos de MongoDB:
1) un témoignage d’un développeur passant de MongoDB à PostgreSQL
Failing with MongoDB
http://blog.schmichael.com/2011/11/05/failing-with-mongodb/
Le développeur en question a réalisé diverses présentations à propos de MongoDB.
Une des diapos montre ce que je mentionnais plus haut: la chute des perfs dès que la taille des données dépasse la capacité RAM.
cf. slide 10 de http://schmichael.com/files/schmongodb/Scaling%20with%20MongoDB%20%28without%20notes%29.pdf
Un autre billet (d’un autre blog) parle de cela:
MongoDB Performance for more data than memory
http://www.colinhowe.co.uk/2011/02/23/mongodb-performance-for-data-bigger-than-memor/
« From doing this it can be seen that the performance of MongoDB can drop by an order of magnitude when the dataset gets too big for memory. However, if the reads are clustered in a subset of the dataset then a large amount of the data will be able to be kept in cache and reads kept quick. »
2) des utilisateurs de Cassandra font état de leur précédente mauvaise expérience avec MongoDB ici:
http://www.slideshare.net/eonnen/from-100s-to-100s-of-millions
3) à propos des upserts et des field level updates
« This makes it sound like upserts and field level updates are just syntactic sugar in MongoDB, their real value being lost if the system is fetching full entries in memory for an update. »
http://nosql.mypopescu.com/post/16760768175/mongodb-tips-and-tricks-more-reads-make-for-faster
4) mais une partie de cette mauvaise expérience vient sans doute du fait que :
« MongoDB 2.0 Should Have Been 1.0 »
http://luigimontanez.com/2011/mongodb-2.0-should-have-been-1.0/
* conclusion
comme dit précédemment: « testez, testez et re-testez » 😉
« MongoDB est utilisé aussi pour collecter les logs de l’application »
A quoi cela sert-il à Photopedia d’utiliser MongoDB pour stocker les logs ?
Font-ils par exemple beaucoup de corrélation de données ?
Bonjour,
La vidéo de la présentation est disponible ici : MongoDB en production chez Fotopedia – une expérience DevOps.
Cyrille (Xebia)
Bonjour,
Si vous avez aimé le témoignage de Fotopedia, nous avons aujourd’hui publié le retour d’expérience MongoDB @ sfr.fr.
Cyrille (Xebia)