Vous êtes sur la page 1sur 315

Rsum

Des bases pour la performance et le Big Data


En quelques annes, le volume des donnes brasses par les entreprises a
considrablement augment. manant de sources diverses (transactions, comportements,
rseaux sociaux, golocalisation), elles sont souvent structures autour dun seul point
dentre, la cl, et susceptibles de crotre trs rapidement. Autant de caractristiques qui
les rendent trs diffi ciles traiter avec des outils classiques de gestion de donnes. Par
ailleurs, lanalyse de grands volumes de donnes, ce quon appelle le Big Data, dfi e
galement les moteurs de bases de donnes traditionnels.
Cest pour rpondre ces diffrentes problmatiques que sont nes les bases de donnes
NoSQL (Not Only SQL), sous limpulsion de grands acteurs du Web comme Facebook ou
Google, qui les avaient dveloppes lorigine pour leurs besoins propres. Grce leur fl
exibilit et leur souplesse, ces bases non relationnelles permettent en effet de grer de gros
volumes de donnes htrognes sur un ensemble de serveurs de stockage distribus, avec
une capacit de monte en charge trs leve. Elles peuvent aussi fournir des accs de
paires cl-valeur en mmoire avec une trs grande clrit. Rserves jusqu peu une
minorit, elles tendent aujourdhui se poser en complment du modle relationnel qui
dominait le march depuis plus de 30 ans.
Du choix de la base NoSQL sa mise en oeuvre
Cet ouvrage dune grande clart dresse un panorama complet des bases de donnes
NoSQL, en analysant en toute objectivit leurs avantages et inconvnients. Dans une
premire partie, il prsente les grands principes de ces bases non relationnelles : interface
avec le code client, architecture distribue, paradigme MapReduce, etc. Il dtaille ensuite
dans une deuxime partie les principales solutions existantes (les solutions de Big Data
autour de Hadoop, MongoDB, Cassandra, Couchbase Server), en prcisant spcifi cits,
forces et faiblesses de chacune. Complte par une tude de cas rel, la dernire partie du
livre est consacre au dploiement concret de ces bases : dans quel cas passer au NoSQL ?
quelle base adopter selon ses besoins ? quelles donnes basculer en NoSQL ? comment
mettre en place une telle base ? comment la maintenir et superviser ses performances ?

Au sommaire
QUEST-CE QUUNE BASE DE DONNES NOSQL ? Des SGBD relationnels au NoSQL Brve histoire des SGBD
Le systme dominant : le modle relationnel dEdgar Frank Codd Lmergence du Big Data et des bases NoSQL
NoSQL versus SQL : quelles diffrences ? Les principes du relationnel en regard du NoSQL Le transactionnel
et la cohrence des donnes Les choix techniques du NoSQL Linterface avec le code client Larchitecture
distribue Le Big Data analytique Les schmas de donnes dans les bases NoSQL Schma implicite Paires
cl-valeur Bases orientes documents ou colonnes Documents binaires Stockage du Big Data analytique
PANORAMA DES PRINCIPALES BASES DE DONNES NOSQL. Hadoop et HBase Installation et architecture Le Big
Data analytique Sqoop et Hive Apache Spark CouchDB et Couchbase Server Mise en oeuvre MongoDB
Mise en oeuvre et administration Riak Mise en oeuvre et administration Redis Mise en oeuvre Cassandra
Caractristiques du moteur Mise en oeuvre Autres bases ElasticSearch Bases de donnes orientes graphe
METTRE EN OEUVRE UNE BASE NOSQL. Quand aller vers le NoSQL et quelle base choisir ? Mettre en place
une solution NoSQL Architecture et modlisation Choisir larchitecture matrielle Mettre en place la solution et
importer les donnes Exemples de dveloppements Maintenir et superviser une base NoSQL Raliser des
tests de charge Supervision avec les outils Linux, les outils intgrs ou Ganglia tude de cas : le NoSQL chez
Skyrock Le dveloppement de solutions en interne Utilisation de Redis Les applications mobiles : Smax.
qui sadresse cet ouvrage ?
Aux experts en bases de donnes, architectes logiciels, dveloppeurs
Aux chefs de projet qui sinterrogent sur le passage au NoSQL

Biographie auteur
R. Bruchez
Consultant informatique indpendant, Rudi Bruchez est expert en bases de donnes depuis
presque vingt ans (certifi cations MCDBA et MCITP). Il assure conseil, ralisation,
expertise et formation pour la modlisation, ladministration et loptimisation des serveurs
et du code SQL, ainsi que des services autour de SQL Server et des solutions NoSQL. Il
est lauteur ou coauteur de plusieurs ouvrages franais et anglais sur SQL Server et SQL,
dont Optimiser SQL Server (ditions Dunod) et SQL (ditions Pearson).
www.editions-eyrolles.com
Les bases de donnes
NoSQL
2e dition et le Big Data
Comprendre
et mettre en oeuvre
Rudi Bruchez
DITIONS EYROLLES
61, bd Saint-Germain
75240 Paris Cedex 05
www.editions-eyrolles.com

DU MME AUTEUR
C. SOUTOU, F. BROUARD, N. SOUQUET et D. BARBARIN. SQL Server 2014.
N13592, 2015, 890 pages.
C. SOUTOU. Programmer avec MySQL (3e dition).
N13719, 2013, 520 pages.
C. SOUTOU. Modlisation de bases de donnes (3e dition).
N14206, 2015, 352 pages. paratre.
C. SOUTOU. SQL pour Oracle (7e dition).
N14156, 2015, 666 pages.
R. BIZO Oracle 12c Administration.
N14056, 2014, 564 pages.
R. BIZO Oracle 12c Sauvegarde et restauration.
N14057, 2014, 336 pages.
R. BIZO SQL pour Oracle 12c.
N14054, 2014, 416 pages.
R. BIZO PL/SQL pour Oracle 12c.
N14055, 2014, 340 pages.
C. PIERRE DE GEYER et G. PONON Mmento PHP et SQL (3e dition).
N13602, 2014, 14 pages.
R. BIZO Oracle 11g Administration.
N12899, 2011, 600 pages.
R. BIZO Oracle 11g Sauvegarde et restauration.
N12899, 2011, 432 pages.
G. BRIARD Oracle 10g sous Windows.
N11707, 2006, 846 pages.
R. BIZO SQL pour Oracle 10g.
N12055, 2006, 650 pages.
G. BRIARD Oracle 10g sous Windows.
N11707, 2006, 846 pages.
G. BRIARD Oracle9i sous Linux.
N11337, 2003, 894 pages.
En application de la loi du 11 mars 1957, il est interdit de reproduire intgralement ou partiellement le prsent ouvrage,
sur quelque support que ce soit, sans lautorisation de lditeur ou du Centre Franais dexploitation du droit de copie,
20, rue des Grands Augustins, 75006 Paris.
Groupe Eyrolles, 2013, 2015, ISBN : 978-2-212-14155-9
Table des matires

AVANT-PROPOS

Un ouvrage impartial
propos des exemples de code
propos de la deuxime dition
PREMIRE PARTIE

Quest-ce quune base NoSQL ?


CHAPITRE 1

Des SGBD relationnels au NoSQL


Brve histoire des systmes de gestion de bases de donnes
Le modle hirarchique
Codasyl et Cobol
Edgard Frank Codd
Le systme dominant : le modle relationnel dEdgar Frank Codd
Les rgles de Codd
De OLTP OLAP
Lmergence du Big Data et des bases NoSQL
Hadoop, une implmentation de MapReduce
BigTable, encore Google !
Linfluence dAmazon
Les volutions du Big Data
Le mouvement NoSQL est-il une avance ?
La nbuleuse NoSQL
Tentatives de classement
Peut-on trouver des points communs entre les moteurs NoSQL ?
CHAPITRE 2

NoSQL versus SQL : quelles diffrences ?


Les principes du relationnel en regard du NoSQL
Les structures de donnes
La modlisation
Le langage SQL
Mfiez-vous des comparaisons
Le dfaut dimpdance
Les NULL
Le transactionnel et la cohrence des donnes
Distribution synchrone ou asynchrone
Le thorme CAP
Journalisation et durabilit de la transaction
Big Data et dcisionnel
CHAPITRE 3

Les choix techniques du NoSQL


Linterface avec le code client
Les fonctionnalits serveur
Les protocoles daccs aux donnes
Larchitecture distribue
La distribution avec matre
La distribution sans matre
La cohrence finale
Le Big Data analytique
Le paradigme MapReduce
Lisp et les langages fonctionnels
Le fonctionnement dHadoop MapReduce
Hadoop 2 YARN
Le Big Data interactif
CHAPITRE 4

Les schmas de donnes dans les bases NoSQL


Le schma implicite
Une approche non relationnelle
Les paires cl-valeur
Les entrepts cl-valeur
Les bases orientes documents
JSON
Les bases orientes colonnes
Les documents binaires
Le stockage du Big Data analytique
Les contraintes de stockage pour Hadoop
Le SequenceFile
Le RCFile
LORC File
Parquet
DEUXIME PARTIE

Panorama des principales bases de donnes NoSQL


Prliminaires
CHAPITRE 5

Hadoop et HBase
Hadoop
Installation
Tester lexcution dHadoop
HBase
Architecture
Installation en mode standalone
Mise en uvre
CHAPITRE 6

Le Big Data Analytique


Prsentation
Sqoop et Hive
Importer les donnes avec Apache Sqoop
Importer les tables dans Hive
Grer les donnes avec Apache Hue
Apache Spark
Caractristiques
Architecture
CHAPITRE 7
CouchDB et Couchbase Server
Prsentation de CouchDB
Caractristiques
Mise en uvre de CouchDB
Utilisation de Futon
Utilisation de lAPI REST
Utilisation de lAPI REST dans le code client
Fonctionnalits du serveur
Programmation client
Prsentation de Couchbase Server
Caractristiques
Fonctionnalits CouchDB
Interface dadministration
Accs Couchbase Server
N1QL
CHAPITRE 8

MongoDB
Prsentation
Caractristiques
Mise en uvre
Linvite interactive
Programmation client
Administration
Scurit
Monte en charge
CHAPITRE 9

Riak
Mise en uvre
Utilisation de lAPI REST
Programmation client
Administration
Configuration du nud
CHAPITRE 10

Redis
Prsentation
Les types de donnes
Mise en uvre
Installation
Configuration
Utilisation de redis-cli
Exemples dapplications clientes
Maintenance
Conclusion
CHAPITRE 11

Cassandra
Caractristiques du moteur
Modle de donnes
Stockage
Mise en uvre
Configuration
LAPI Thrift
Gestion de la cohrence
Programmation client
Nodetool
Conclusion
CHAPITRE 12

Les autres bases de donnes de la mouvance NoSQL


ElasticSearch
Mise en uvre
Les bases de donnes orientes graphes
Neo4j
TROISIME PARTIE

Mettre en uvre une base NoSQL


CHAPITRE 13
Quand aller vers le NoSQL et quelle base choisir ?
Aller ou non vers le NoSQL
Les avantages des moteurs relationnels
Que doit-on stocker ?
La diffrence dapproche avec le relationnel
Le problme des comptences
Quels sont les besoins transactionnels ?
Rsum des cas dutilisation
Quelle base choisir ?
En rsum
Conclusion
CHAPITRE 14

Mettre en place une solution NoSQL


Architecture et modlisation
Stocker du XML
Conception pilote par le domaine
La cohrence
Design patterns
Choisir larchitecture matrielle
valuer les besoins en mmoire de Redis
valuer les besoins disque
Mettre en place la solution et importer les donnes
Dploiement distribu
Outils de gestion de configuration
Importer les donnes
Importer du XML
Exemples de dveloppements
CHAPITRE 15

Maintenir et superviser ses bases NoSQL


Raliser des tests de charge
Redis
Cassandra
Tests gnriques
Supervision avec les outils Linux
La commande iostat
La commande pidstat
La commande sar
Supervision avec les outils intgrs
MongoDB
Cassandra
Redis
Supervision avec Ganglia
Installer Ganglia
Ajouter des modules Python
CHAPITRE 16

tude de cas : le NoSQL chez Skyrock


Le dveloppement de solutions en interne
Topy
Fluxy
Lutilisation de Redis
Tester la charge
Contourner les problmes
Utiliser Redis pour le traitement dimages
Les applications mobiles : Smax
Exemple de requtes gographiques dans MongoDB
CONCLUSION

Comment se prsente le futur ?


INDEX
Avant-propos

Ce quon appelle le mouvement NoSQL est encore relativement jeune en France,


mme sil existe depuis plusieurs annes aux tats-Unis. Mais il suscite dj un vif intrt
et de nombreux dbats, plus que ne lont fait les prcdents carts par rapport au modle
dominant de la gestion des bases de donnes, savoir le modle relationnel.
Lune des principales raisons de cet intrt provient de son approche pragmatique. Les
moteurs non relationnels regroups sous la bannire du NoSQL ont t souvent conus
sous limpulsion dentreprises qui voulaient rpondre leurs propres besoins. Ils sont
galement les produits de leur temps, o les machines sont moins chres et la distribution
sur plusieurs nuds est lune des solutions les plus accessibles de monte en charge.
On pourrait aussi considrer le NoSQL comme le fruit dune vieille opposition entre le
dveloppeur, qui souhaite utiliser ses outils rapidement, de manire presque ludique, et
sans aucune contrainte, et ladministrateur, qui protge son systme et met en place des
mcanismes complexes et contraignants.1 Dailleurs, beaucoup de dveloppeurs naiment
pas les bases de donnes. Ils sont pourtant obligs de sen servir, car linformatique
manipule de linformation, laquelle est stocke dans des systmes de gestion de bases de
donnes (SGBD). Ils vivent comme une intrusion cet lment externe, qui sintgre mal
avec leur code, et qui les oblige apprendre un langage supplmentaire, faussement facile,
le SQL.
Mais le mouvement NoSQL ne peut se rsumer ce rejet du SQL : certains de ses moteurs
sont le rsultat de recherches et dexprimentations. Dautres permettent de garantir les
meilleures performances possibles en conservant un modle de donnes trs simple. Sous
la bannire NoSQL, ces outils ont ainsi des identits diffrentes et rpondent des besoins
divers, allant du temps rel au Big Data.

Un ouvrage impartial
Cest pourquoi crire un livre sur le NoSQL dans son ensemble pourrait paratre un peu
artificiel, puisque en fin de compte, la seule composante qui runit des outils comme
Cassandra, MongoDB ou Redis, cest labandon du modle relationnel. Mais somme
toute, ce nest pas quun petit point commun. Le modle relationnel est le modle
dominant depuis la fin des annes 1980, cela fait plus de trente ans maintenant. Sloigner
de ce modle comme le font les moteurs NoSQL implique de dvelopper de nouvelles
stratgies, de nouveaux algorithmes et de nouvelles pratiques pour la gestion des donnes.
Il y a donc des points communs, des fertilisations croises que nous allons dtailler dans
ce livre.
Comme beaucoup de nouvelles technologies qui rencontrent un certain succs, les moteurs
NoSQL font lobjet de dbats parfois exagrs, o les arguments manquent de prcision et
dobjectivit. Pour exemple, voici un extrait traduit de lintroduction du livre Hbase, the
Definitive Guide (Lars George, OReilly, 2011), o lauteur justifie lutilisation de HBase
plutt quun moteur relationnel dans les cas de forte monte en charge :
La popularit de votre site augmentant, on vous demande dajouter de nouvelles
fonctionnalits votre application, ce qui se traduit par plus de requtes vers votre base
de donnes. Les jointures SQL que vous tiez heureux dexcuter par le pass ralentissent
soudainement et ne se comportent plus de faon satisfaisante pour monter en charge. Vous
devrez alors dnormaliser votre schma. Si les choses continuent empirer, vous devrez
aussi abandonner lutilisation de procdures stockes, parce quelles deviennent trop
lentes. En fin de compte, vous rduisez le rle de votre base de donnes un espace de
stockage en quelque sorte optimis pour vos types daccs.
Votre charge continuant augmenter et de plus en plus dutilisateurs senregistrant sur
votre site, ltape logique suivante consiste prmatrialiser de temps en temps les
requtes les plus coteuses, de faon pouvoir fournir plus rapidement les donnes vos
clients. Puis vous commencez supprimer les index secondaires, car leur maintenance
devient trop pnible et ralentit la base de donnes. Vous finissez par excuter des requtes
qui peuvent utiliser seulement la cl primaire, et rien dautre.
Vous avez peut-tre maintenant les yeux carquills, comme je les ai eus en lisant ce texte.
Pour lauteur, la solution pour optimiser les accs un moteur relationnel est de
dnormaliser, supprimer les jointures, bannir les procdures stockes et enlever les index.
Or un moteur relationnel peut justement monter en charge grce aux optimisations
apportes par la normalisation, lindexation et les procdures stockes qui vitent des
allers-retours entre le client et le serveur. Ce genre dapproximations et de contrevrits
sur le modle relationnel est assez commun dans le monde NoSQL. Est-ce que, pour
autant, les propos cits ici sont faux ? Pas forcment, cela dpend du contexte et cest a
qui est important. Dans une utilisation analytique des donnes, qui force parcourir une
grande partie des tables, les jointures peuvent rellement poser problme, surtout si elles
sexcutent sur un moteur comme MySQL, que beaucoup dutilisateurs du NoSQL
connaissent bien parce quils sont aussi des dfenseurs du logiciel libre. MySQL navait
jusqu trs rcement quun seul algorithme de jointure, la boucle imbrique, qui est
inefficace si le nombre de lignes joindre est important. Quoi quil en soit, il est important
de prciser de quel contexte on parle pour ne pas induire le lecteur en erreur.
En face, lincomprhension est galement souvent constate, et le danger qui guette toute
discussion sur le sujet est de se transformer en une guerre dcoles, o les spcialistes et
dfenseurs du modle relationnel rejettent avec mpris le mouvement NoSQL, en ignorant
les raisons du dveloppement et de lengouement de ces systmes qui tiennent en partie
aux difficults et limitations du relationnel.
Tout cela cre des querelles de clocher qui feront des victimes : les utilisateurs et les
entreprises qui, eux, recherchent objectivement la meilleure solution de stockage et de
gestion de leurs donnes. Ce livre se propose donc de clarifier la situation, en comparant
les deux modles, en identifiant leurs points forts et leurs faiblesses, mais aussi en
essayant de dbusquer ce qui se cache derrire les choix de conception des diffrents
moteurs NoSQL. En effet, nous pensons quune vision densemble de loffre de ces
nouveaux moteurs vous permettra de vous orienter dans vos choix de dveloppement.
Bien entendu, lapproche de cet ouvrage sera galement pratique et dmonstrative : nous
vous expliquerons comment fonctionnent les moteurs NoSQL les plus populaires,
pourquoi et comment les choisir, et comment mettre le pied ltrier.

propos des exemples de code


Dans ce livre, nous allons expliquer comment manipuler des bases de donnes NoSQL, en
prsentant leurs interfaces, leurs invites de commande, ainsi que des exemples de code
client. Pour ces exemples, nous avons choisi dutiliser Python, principalement parce que
cest un langage trs populaire qui compte de nombreux pilotes pour les moteurs NoSQL,
et parce que la clart de sa syntaxe le rend facile lire et propice lapprentissage.
Python, un langage de choix
Peut-tre pensez-vous que Python nest pas un langage dentreprise au mme titre que C++, C# ou Java ?
Dtrompez-vous. Cest un langage puissant qui est de plus en plus utilis dans les projets de grande ampleur. Le site
codeeval.com, qui permet ses membres dvaluer leur comptence en programmation, publie chaque anne une
estimation de la popularit des langages de programmation, base sur des tests de codage pour plus de 2 000
entreprises. Le rsultat de lanne 2014 (http://blog.codeeval.com/codeevalblog/2014) met ainsi Python au premier
rang pour la quatrime anne conscutive, avec 30,3 % de popularit.

Toutes nos installations et nos exemples seront raliss sur une machine Linux, dote de la
distribution Ubuntu Server 14.04 LTS. Python y figurant par dfaut, il vous restera
installer pip (Python Package Index), lutilitaire de gestion de paquets Python, qui nous
servira rcuprer les diffrents paquets comme les pilotes pour nos moteurs. Voici la
procdure dinstallation de pip sur Ubuntu.
Installez dabord les paquets suivants laide de apt-get, le gestionnaire de paquets de
Debian et dUbuntu :
sudo apt-get install python-pip python-dev build-essential

Puis procdez la mise jour de pip :


sudo pip install --upgrade pip

propos de la deuxime dition


Depuis la parution de la premire dition de cet ouvrage, le paysage du NoSQL a
beaucoup volu. Cette nouvelle dition a t remanie en de nombreux points. Nous
avons allg la partie thorique sur les diffrences entre SQL et NoSQL, afin de consacrer
plus de pages une considration essentielle : la nature et le mode dutilisation des bases
de donnes NoSQL. Nous avons galement rduit certaines portions de code, notamment
celles dtaillant linstallation des moteurs NoSQL, pour traiter de sujets plus importants
comme les forces et les faiblesses de chacun de ces moteurs, les cas pratiques dutilisation
et leurs principales fonctionnalits. Par ailleurs, nous avons nettement augment la place
du Big Data car il sagit du thme dont lactualit est la plus forte. Les moteurs NoSQL
distribus et les mthodes de traitement distribu sont en pleine volution actuellement et
il est capital de comprendre les enjeux de ces dveloppements pour traiter de larges
volumes de donnes.
1. Un mouvement, nomm DevOps, essaie dailleurs de concilier ces deux points de vue.
Partie I

Quest-ce quune base NoSQL ?

Le terme NoSQL a t invent en 2009 lors dun vnement sur les bases de donnes
distribues. Le terme est vague, incorrect (certains moteurs NoSQL utilisent des variantes
du langage SQL, par exemple Cassandra), mais prsente lavantage davoir un effet
marketing et polmique certain. Dans cette partie, nous allons aborder les caractristiques
gnrales des moteurs NoSQL, historiquement, conceptuellement et techniquement, en
regard des bases de donnes relationnelles, mais aussi indpendamment de cette rfrence.
1
Des SGBD relationnels au NoSQL

Les dfenseurs du mouvement NoSQL le prsentent comme une volution bienvenue de


lantique modle relationnel. Ses dtracteurs le considrent plutt comme une rgression.
Le modle relationnel est apparu dans les annes 1970, devenant rapidement le modle
dominant, et jamais dtrn depuis, un peu comme les langages impratifs (comme C++ et
Java) dans le domaine de la programmation. Dans ce chapitre, nous allons prsenter un
bref historique de lvolution des bases de donnes informatiques, pour mieux comprendre
do viennent les modles en prsence, pourquoi ils ont vu le jour et ont ensuite volu.

Brve histoire des systmes de gestion de bases de donnes


Le besoin dorganiser les donnes, potentiellement de grandes quantits de donnes, afin
den optimiser la conservation et la restitution, a toujours t au cur de linformatique.
La faon dont nous nous reprsentons lordinateur est une mtaphore du cerveau humain.
Il nous est vident que llment central du fonctionnement intellectuel est la mmoire.
Sans le stock dinformations que constitue la mmoire humaine, il nous est impossible de
produire le moindre raisonnement, car ce dernier manipule des structures, des lments
connus, reconnus et compris, qui proviennent de notre mmoire.
Stocker et retrouver, voil les dfis de la base de donnes. Ces deux lments centraux se
dclinent bien sr en diffrentes sous-fonctions importantes, comme assurer la scurit ou
se protger des incohrences. Comme nous allons le voir dans ce chapitre, ces sous-
fonctions ne font pas lunanimit. Depuis toujours, les avis divergent en ce qui concerne
les responsabilits assures par un systme de gestion de bases de donnes.
Ainsi, les premiers dfis des SGBD furent simplement techniques et concernaient des
fonctions importantes, stocker et retrouver. Un systme grant des donnes doit tre
capable de les maintenir sur une mmoire de masse, comme on disait il y a quelques
dcennies, et doit offrir les fonctions ncessaires pour retrouver ces donnes, souvent
laide dun langage ddi. Les dbuts furent un peu de la mme veine que ce que nous
voyons aujourdhui dans le monde des bases NoSQL : une recherche parallle de
diffrents modles.

Le modle hirarchique
Le modle hirarchique est historiquement la premire forme de modlisation de donnes
sur un systme informatique. Son dveloppement commena dans les annes 1950.
On lappelle modle hirarchique cause de la direction des relations qui stablissent
uniquement du parent vers les enfants. Une base de donnes hirarchique est compose
denregistrements (records) qui contiennent des champs et qui sont regroups en types
denregistrements (record types). Des relations sont cres entre types denregistrements
parents et types denregistrements fils, ce qui forme un arbre hirarchique. La diffrence
majeure entre ce modle et le modle relationnel que nous connaissons maintenant, est la
limitation de larbre : il ne peut y avoir quun seul arbre et les relations ne peuvent se
dessiner que du parent vers lenfant. Les choix de relations sont donc trs limits.
Limplmentation la plus connue du modle hirarchique est le moteur IMS (Information
Management System) dIBM, auparavant nomm ICS (Information Control System), qui
fut notamment dvelopp dans le but dassurer la gestion des matriaux de construction du
programme spatial de la NASA pour envoyer des hommes sur la Lune dans les annes
1960. IMS existe toujours et selon IBM, la meilleure anne du moteur en termes de ventes
a t 2003.

Codasyl et Cobol
En 1959, le Codasyl (Conference on Data Systems Languages, en franais Confrence sur
les langages de systmes de traitement de donnes) conduit la cration dun consortium
dont lobjectif tait de dvelopper des standards de gestion de donnes et ce
dveloppement dun langage daccs ces donnes. Les membres du Codasyl taient des
entreprises, des universitaires et des membres du gouvernement. Ils tablirent dabord un
langage dinterrogation de donnes, le fameux Cobol (COmmon Business Oriented
Language). Ce dernier fut dvelopp la mme anne luniversit de Pennsylvanie. Cobol
fait lobjet dune norme ISO qui, comme la norme SQL, volua en plusieurs versions.
Cest un langage quon nomme navigationnel : des pointeurs sont poss et maintenus
sur une entit, appele entit courante , et le pointeur se dplace au gr des besoins vers
dautres entits. Quand on travaille avec plusieurs entits, chaque entit a son pointeur
maintenu sur un article. Il sagit dune approche purement procdurale laccs aux
donnes : parcourir les ensembles dentits implique dcrire des boucles (en utilisant des
commandes comme FIND FIRST et FIND NEXT) qui testent des critres et traitent les donnes
ainsi filtres, par exemple.
Aprs avoir tabli le langage de traitement de donnes, les membres du Codasyl tablirent
un standard de structuration des donnes, quon nomme modle de donnes rseau .
Fondamentalement, il annonce le modle relationnel. Le modle rseau permet de dcrire
des liens entre des articles. Ces liens sont appels des sets, et on peut les considrer, si on
veut faire une comparaison avec le modle relationnel, comme des tables de
correspondance entre des articles, propritaire dun ct et type membre de lautre. Les
systmes de gestion de bases de donnes rseau nont pas llgance du modle
relationnel, principalement cause de leur langage de requte, complexe et navigationnel
(Cobol).

Edgard Frank Codd


Edgar Frank Codd est un sujet britannique qui tudia les mathmatiques et la chimie en
Angleterre, et qui se rendit aux tats-Unis en 1948 pour travailler comme programmeur
pour IBM. Il obtint son doctorat de Computer Science luniversit du Michigan. Au
milieu des annes 1960, il commena travailler comme chercheur aux laboratoires de
recherche dIBM San Jose, en Californie. Cest dans ce laboratoire quil labora
lorganisation des donnes selon un modle bas sur la thorie mathmatique des
ensembles. Il publia ce sujet un document interne en 1969, pour exposer sa thorie au
sein dIBM. Malheureusement, les investissements effectus par la socit dans le systme
IMS nincitrent pas IBM sintresser ce modle diffrent. Un an plus tard, Codd
publia donc un article intitul A Relational Model of Data for Large Shared Data Banks
dans Communications of the ACM, revue de lassociation pour la machinerie
informatique (Association for Computing Machinery). Cette association but non lucratif
fut fonde en 1947 pour favoriser la recherche et linnovation. Elle est toujours active
aujourdhui. Larticle pose les bases du modle relationnel en indiquant les bases
mathmatiques et algbriques de relations. Il est disponible ladresse suivante :
http://www.acm.org/classics/nov95/toc.html.

Les relations
Le modle de Codd privilgiait un systme de relations bas uniquement sur les valeurs
des donnes, contrairement dautres types de relations utilisant des pointeurs sur des
entits (modle rseau), et une manipulation de ces donnes laide dun langage de haut
niveau implmentant une algbre relationnelle, sans se proccuper du stockage physique
des donnes. Cette approche permet disoler laccs aux donnes de limplmentation
physique, et mme de le faire sur plusieurs niveaux travers le mcanisme des vues, et
dexprimer des requtes dans un langage beaucoup plus compact que de manire
procdurale comme en Cobol. Il sagit dun langage dclaratif, algbrique, en quelque
sorte fonctionnel, qui ne soccupe pas des algorithmes informatiques de manipulation des
donnes. A priori, cette pense est plutt trange : comment concevoir quun langage de
haut niveau, qui ne soccupe que de dcrire les rsultats doprations sur des donnes sans
jamais spcifier le comment, puisse tre efficace. Pour sassurer des meilleures
performances, il faut normalement tre au plus proche de la machine. Lhistoire du modle
relationnel a montr que cette pense tait errone dans ce cas : une description correcte
de la requte dclarative, allie un moteur doptimisation efficace du ct du serveur
permet au contraire doptimiser automatiquement les performances.

Le dveloppement des moteurs relationnels


En 1974, le laboratoire de San Jose commena dvelopper un prototype, le System R,
pour exprimenter les concepts avancs par Codd. Ils dvelopprent un langage de
manipulation de donnes nomm Sequel (Structured English Query Language) et un
moteur en deux parties, RSS (Research Storage System) et RDS (Relational Data System),
une sparation utilise de nos jours dans tous les moteurs relationnels sous forme de
moteur de stockage et de moteur relationnel et qui permet effectivement la sparation
entre la gestion physique et la gestion logique des donnes. System R est lanctre de tous
les moteurs de bases de donnes relationnelles contemporains et a introduit un certain
nombre de concepts qui constituent encore aujourdhui la base de ces moteurs, comme
loptimisation de requtes ou les index en B-tree (arbre balanc). Comme Sequel tait une
marque dpose par une compagnie britannique, le nom du langage fut chang en SQL.
En mme temps, luniversit de Berkeley, Eugene Wong et Michael Stonebraker
sinspirrent des travaux de Codd pour btir un systme nomm Ingres, qui aboutira plus
tard PostgreSQL, Sybase et Informix. De son ct, vers la fin des annes 1970, Larry
Ellison sinspira aussi des travaux de Codd et de System R pour dvelopper son moteur de
bases de donnes, Oracle, dont la version 2 fut en 1979 le premier moteur relationnel
commercial. IBM transforma System R en un vrai moteur commercial, nomm SQL/DS,
qui devint par la suite DB2.

Le systme dominant : le modle relationnel dEdgar Frank


Codd
partir des annes 1980, le modle relationnel supplanta donc toutes les autres formes de
structuration de donnes. System R avait prouv quun langage dclaratif pouvait savrer
tre un excellent choix pour une interrogation performante des donnes. Oracle, DB2 et
les descendants dIngres furent les implmentations qui rendirent les SGBDR populaires
auprs des entreprises et des universits.
Le modle relationnel a dvelopp notre vision de ce quest ou doit tre une base de
donnes, pour des dcennies : sparation logique et physique, langage dclaratif,
structuration forte des donnes, reprsentation tabulaire, contraintes dfinies au niveau du
moteur, cohrence transactionnelle forte, etc. Ces caractristiques ont t graves dans le
marbre par Edgar Codd grce ce quon appelle les douze rgles de Codd .
Les douze rgles de Codd
Ce quon appelle les douze rgles de Codd sont en fait numrotes de 0 12, il y en a donc treize. Une erreur
classique de base zro.

Elles parurent en octobre 1985 dans le magazine ComputerWorld dans deux articles
maintenant clbres : Is Your DBMS Really Relational? et Does Your DBMS Run By
the Rules? .

Les rgles de Codd


Vous trouverez ci-aprs celles qui nous intressent le plus pour la suite de ce livre.
Rgle 0 Toutes les fonctionnalits du SGBDR doivent tre disponibles travers le
modle relationnel et le langage dinterrogation.
Rgle 1 Toutes les donnes sont reprsentes par des valeurs prsentes dans des
colonnes et des lignes de tables.
Rgle 3 Une cellule peut ne pas contenir de valeur, ou exprimer que la valeur est
inconnue, laide du marqueur NULL. Il sagit dun indicateur spcial, distinct de toute
valeur et trait de faon particulire.
Rgle 5 Le SGBDR doit implmenter un langage relationnel qui supporte des
fonctionnalits de manipulation des donnes et des mtadonnes, de dfinition de
contraintes de scurit et la gestion des transactions.
Rgle 10 Indpendance dintgrit : les contraintes dintgrit doivent tre
indpendantes des programmes clients et doivent tre stockes dans le catalogue du
SGBDR. On doit pouvoir modifier ces contraintes sans affecter les programmes clients.
Rgle 11 Indpendance de distribution : la distribution ou le partitionnement des
donnes ne doivent avoir aucun impact sur les programmes clients.
Rgle 12 Rgle de non-subversion : aucune interface de bas niveau ne doit permettre
de contourner les rgles dictes. Dans les faits, cette rgle implique quil nest possible
dinterroger et de manipuler le SGBDR qu travers son langage relationnel.
Lensemble de ces rgles indique la voie suivre pour les systmes de gestion de bases de
donnes relationnelles. Elles concernent le modle sous-jacent des bases dites SQL et ne
sont jamais totalement implmentes, cause des difficults techniques que cela
reprsente.

De OLTP OLAP
partir des annes 1980, les moteurs relationnels ont donc pris le pas sur les autres
systmes pour les besoins de tous types de donnes, dabord pour les systmes
dentreprises ou dacadmies, puis auprs de dveloppeurs indpendants pour des
initiatives libres ou personnelles, comme des logiciels shareware, des sites web, etc.
Mme pour des petits besoins, des moteurs embarqus ou locaux comme SQLite
(http://www.sqlite.org/) sont largement utiliss.
Assez rapidement, pourtant, un besoin diffrent sest manifest : le modle relationnel est
performant pour une utilisation purement transactionnelle, ce quon appelle OLTP (Online
Transactional Processing). Une base de donnes de gestion, par exemple, quon utilise
dans les PGI (Progiciels de gestion intgre, ERP en anglais pour Enterprise Resource
Planning), prsente une activit permanente de mises jour et de lectures de jeux de
rsultats rduits. On interroge la table des factures filtres pour un client, ce qui retourne
une dizaine de lignes, on requte la table des paiements pour vrifier que ce client est bien
solvable, si cest le cas, on ajoute une facture comportant des lignes de factures, et pour
chaque produit ajout, on dcrmente son stock dans la table des produits. Toutes ces
oprations ont une envergure limite dans des tables dont la cardinalit (le nombre de
lignes) peut tre par ailleurs importante. Mais, par les vertus dune bonne modlisation des
donnes et grce la prsence dindex, chacune de ces oprations est optimise.
Mais quen est-il des besoins statistiques ? Comment rpondre aux demandes de tableaux
de bord, danalyses historiques voire prdictives ? Dans un PGI, cela peut tre une analyse
complte des tendances de ventes par catgories de produits, par succursales, par rayons,
par mois, par type de clients, sur les cinq dernires annes, en calculant les volutions
pour dterminer quelles catgories de produits voluent dans quelle rgion et pour quelle
clientle, etc. Dans ce genre de requte, quon appelle OLAP (Online Analytical
Processing), qui doit parcourir une grande partie des donnes pour calculer des agrgats,
le modle relationnel, les optimiseurs de requte des SGBDR et lindexation ne permettent
pas de rpondre de manire satisfaisante au besoin.

Le schma en toile
Un modle diffrent a alors merg, avec une structuration des donnes adapte de
larges parcours de donnes volumineuses. Ce modle est orient autour du schma en
toile ou en flocon. Faisons la diffrence entre un modle normalis trs simple, comme
celui reproduit sur la figure 1-1 et un modle OLAP en toile, tel que celui reprsent sur
la figure 1-2.

Figure 1-1
Modle normalis OLTP

Figure 1-2
Modle OLAP en toile

Nous verrons plus loin en quoi consiste la normalisation. Pour linstant, nous souhaitons
simplement montrer comment les structures de donnes se sont modifies suite
lvolution des besoins des entreprises, laquelle dpend aussi de laugmentation du
volume des donnes manipules par le systme dinformation. Le modle OLAP a vu le
jour en raison de laugmentation du stockage de donnes agrges et historiques
concernant le fonctionnement et le mtier des entreprises, et des besoins de requtes
globales sur ces grands volumes pour des besoins analytiques. Cest ce quon appelle le
dcisionnel ou la Business Intelligence : lutilisation des donnes pour lanalyse et la
connaissance du mtier, des caractristiques commerciales, marketing et comptables de
lentreprise.
Ce modle, qui a aussi t formalis par Codd et son quipe, prfigure ce quon appelle
aujourdhui le Big Data. la base, linterrogation du modle OLAP se fait travers une
vision dite cube ou hypercube , intgre dans des outils danalyse, et qui permet de
manipuler les donnes agrges selon un nombre thoriquement infini de dimensions, qui
sont justement les axes danalyse dont nous parlions. Nous verrons que laugmentation
exponentielle du volume des donnes aboutit aujourdhui chercher de nouvelles faons
ou en tout cas des faons complmentaires de traiter et danalyser les donnes
dcisionnelles et mme celles en temps rel.

Lmergence du Big Data et des bases NoSQL


Les volutions logicielles suivent assez naturellement les volutions matrielles. Les
premiers SGBD taient construits autour de mainframes et dpendaient des capacits de
stockage de lpoque. Le succs du modle relationnel est d non seulement aux qualits
du modle lui-mme mais aussi aux optimisations de stockage que permet la rduction de
la redondance des donnes. Avec la gnralisation des interconnexions de rseaux,
laugmentation de la bande passante sur Internet et la diminution du cot de machines
moyennement puissantes, de nouvelles possibilits ont vu le jour, dans le domaine de
linformatique distribue et de la virtualisation, par exemple.
Le passage au XXIe sicle a vu les volumes de donnes manipules par certaines
entreprises ou organismes, notamment ceux en rapport avec Internet, augmenter
considrablement. Donnes scientifiques, rseaux sociaux, oprateurs tlphoniques, bases
de donnes mdicales, agences nationales de dfense du territoire, indicateurs
conomiques et sociaux, etc., linformatisation croissante des traitements en tout genre
implique une multiplication exponentielle de ce volume de donnes qui se compte
maintenant en ptaoctets (100 000 traoctets). Cest ce que les Anglo-Saxons ont appel le
Big Data. La gestion et le traitement de ces volumes de donnes sont considrs comme
un nouveau dfi de linformatique, et les moteurs de bases de donnes relationnelles
traditionnels, hautement transactionnels, semblent totalement dpasss.

La solution Google
Google est probablement la socit la plus concerne par la manipulation de grands
volumes de donnes, cest pourquoi elle a cherch et dvelopp une solution visant
relever ces dfis. Google doit non seulement grer un volume extrmement important de
donnes afin dalimenter son moteur de recherche, mais aussi ses diffrentes offres,
comme Google Maps, YouTube, Google Groupes et bien sr son offre doutils comme
Gmail ou Google Drive. Cela ncessite non seulement un stockage de donnes trs
important, mais aussi des besoins de traitements sur ces volumes.
Afin de permettre le stockage de ces grands volumes de donnes, Google a dvelopp il y
a plus de dix ans un systme de fichiers distribu nomm GoogleFS, ou GFS, systme
propritaire utilis seulement chez Google. Fin 2003, au symposium de lACM
(Association for Computing Machinery) sur les principes de systmes dexploitation
Lake George, des ingnieurs de Google (Sanjay Ghemawat, Howard Gobioff et Shun-Tak
Leung) firent une prsentation de Google FS, intitule The Google File System
(http://research.google.com/archive/gfs.html). En 2003 dj, le systme de fichiers
distribu de Google avait fait ses preuves et tait intensivement utilis en production, ce
qui prouvait la viabilit de la solution technique. Le but de GFS tait doffrir un
environnement de stockage redondant et rsilient fonctionnant sur un cluster constitu
dun grand nombre de machines de moyenne puissance, jetables (le terme anglo-saxon
est commodity hardware). Quelques mois plus tard, en 2004, loccasion du sixime
symposium OSDI (Operating System Design and Implementation) San Francisco,
Jeffrey Dean et le mme Sanjay Ghemawat de Google prsentrent un autre pilier de leur
solution technique. Le titre de la prsentation tait MapReduce: Simplified Data
Processing on Large Clusters (http://research.google.com/archive/mapreduce.html).
Comme nous le verrons plus en dtail, il sagissait, en plus de stocker les donnes sur
GFS, de pouvoir effectuer des traitements sur ces donnes de faon galement distribue
et de pouvoir en restituer les rsultats. Pour ce faire, les ingnieurs de Google se sont
inspirs des langages fonctionnels et en ont extrait deux primitives, les fonctions Map et
Reduce. la base, Map permet deffectuer un traitement sur une liste de valeurs. En le
ralisant sur GFS et en regroupant les rsultats grce la fonction Reduce, Google avait
russi btir un environnement de traitement distribu qui lui a permis de rsoudre un
grand nombre de problmes.

Hadoop, une implmentation de MapReduce


Doug Cutting, le dveloppeur du moteur de recherche en plein texte Lucene, cherchait un
moyen de distribuer le traitement de Lucene pour btir le moteur dindexation web libre
Nutch. Sinspirant de la publication sur GFS, il cra avec dautres contributeurs du projet
une implmentation libre en Java nomme dabord NDFS (Nutch Distributed File
System). Afin de permettre un traitement distribu des donnes accumules par Nutch,
Doug Cutting entama alors une implmentation libre de MapReduce en Java, quil appela
Hadoop, du nom de llphant doudou de son fils. Nous en reparlerons plus loin ainsi que
de sa mise en uvre. NDFS fut ensuite renomm HDFS (Hadoop Distributed FileSystem).
Dabord financ par Yahoo! o Doug Cutting tait lpoque employ, donn la
fondation Apache ensuite, Hadoop est devenu un projet dune grande popularit,
implment par de plus en plus de socits, jusqu Microsoft qui a annonc dbut 2012
son soutien au projet, et la disponibilit dHadoop sur son service de cloud, Windows
Azure, ainsi que sur Windows Server. Au Hadoop Summit 2012, Yahoo! a indiqu que 42
000 serveurs tournaient avec Hadoop, et que leur plus gros cluster Hadoop tait compos
de 4 000 machines, bientt 10 000 pour la sortie de Hadoop 2.0. Par ailleurs, en juin 2012,
Facebook a annonc sur son site que leur installation dHDFS atteignait le volume
physique de 100 ptaoctets (http://www.facebook.com/notes/facebook-engineering/under-
the-hood-hadoop-distributed-filesystem-reliability-with-namenode-and-
avata/10150888759153920).

BigTable, encore Google !


En 2004, Google commena btir un systme de gestion de donnes bas sur GFS :
BigTable. En 2006, encore loccasion du symposium OSDI, des ingnieurs de Google
firent une prsentation nomme BigTable: A Distributed Storage System for Structured
Data. BigTable ressemble une gigantesque table de hachage distribue qui incorpore des
mcanismes permettant de grer la cohrence et la distribution des donnes sur GFS. Une
fois de plus, cette prsentation de Google inspira la cration dimplmentations libres,
dont la plus notable est HBase. Cette dernire a t dveloppe lorigine par la socit
Powerset, active dans le domaine de la recherche en langage naturel. Leur besoin tait de
traiter de larges volumes dinformations pour dvelopper leur moteur de recherche. Se
basant sur Hadoop et HDFS, ils ajoutrent la couche correspondant BigTable. partir de
2006, deux dveloppeurs de Powerset, Michael Stack et Jim Kellerman, galement
membres du comit de gestion dHadoop, furent ddis plein temps au dveloppement
de Hbase, projet libre qui commena comme une contribution Hadoop et devint un
projet indpendant de la fondation Apache en janvier 2008. En juillet 2008, Microsoft
racheta Powerset pour intgrer leur technologie dans son moteur de recherche Bing. Aprs
deux mois dinactivit, Microsoft permit aux dveloppeurs de Powerset de continuer leur
contribution plein temps au projet libre.
HBase est devenu depuis un des projets phares du monde NoSQL. Il sagit dun systme
de gestion de donnes orient colonnes (voir page 21) destin manipuler de trs larges
volumes de donnes sur une architecture totalement distribue. Il est utilis par des acteurs
majeurs du Web, comme Ebay, Yahoo! et Twitter, de mme que par des socits telles
quAdobe. Pour consulter une liste non exhaustive des socits utilisant Hbase, rendez-
vous ladresse suivante : http://wiki.apache.org/hadoop/Hbase/PoweredBy.

Linfluence dAmazon
En octobre 2007, Werner Vogels, Chief Technical Officer dAmazon annonce sur son blog,
All Things Distributed
(http://www.allthingsdistributed.com/2007/10/amazons_dynamo.html), quAmazon va
prsenter un papier au 21e symposium sur les principes des systmes dexploitation
(Symposium on Operating Systems Principles) organis par lACM. Cette prsentation
concerne une technologie quAmazon a nomm Dynamo
(http://www.allthingsdistributed.com/2007/10/amazons_dynamo.html) et comme celle de
Google, sa lecture est trs intressante. Dynamo consiste en un entrept de paires cl-
valeur destin tre lui aussi totalement distribu, dans une architecture sans matre.
Dynamo utilise un certain nombre de technologies typiques du monde NoSQL que nous
dtaillerons au chapitre 3 consacr aux choix techniques du NoSQL. Ceci dit, si les
moteurs NoSQL implmentent ces technologies, cest aussi grce au papier dAmazon.
Cette communication a eu une grande influence dans le monde NoSQL et plusieurs projets
se sont bass sur les technologies prsentes pour btir leur solution libre. Dynamo,
comme BigTable de Google, est rest la proprit dAmazon et le code nest donc pas
disponible.
Un mouvement pragmatique
Voici la traduction dun passage intressant de larticle de Werner Vogels :
Nous avons beaucoup de chance que le papier ait t slectionn pour publication par le SOSP ; trs peu de
systmes rellement utiliss en production ont t prsents durant ces confrences, et de ce point de vue, il sagit
dune reconnaissance du travail fourni pour crer un systme de stockage capable rellement de monter en charge
de faon incrmentielle, et dans lequel les proprits les plus importantes peuvent tre configures de faon
approprie.

Dans les nouvelles tendances de linformatique, il y a toujours une part de rponse des
besoins rels de dveloppement, dinvention, de sophistication technique, et une part de
mode, dinvestissement de grands acteurs du domaine pour dvelopper ou renforcer leur
prsence, et videmment pour ne pas se laisser distancer en manquant un rendez-vous
avec le futur. Le NoSQL fait partie de ces phnomnes, mais il prsente aussi lavantage
dtre un mouvement trs pragmatique. Comme nous le verrons, nombre de moteurs
NoSQL sont dvelopps par les entreprises elles-mmes, qui les utilisent en production
afin de rpondre leurs propres besoins.

Apache Cassandra
Avinash Lakshman, un des dveloppeurs de Dynamo, fut recrut par Facebook pour crer
un entrept de donnes destin mettre en place la fonctionnalit de recherche dans les
botes aux lettres des comptes Facebook, qui permet aux utilisateurs deffectuer des
recherches parmi tous les messages reus. En collaboration avec un autre ingnieur,
Prashant Malik, prcdemment Senior Engineer chez Microsoft, il dveloppa un entrept
orient colonnes totalement dcentralis, mlangeant donc les technologies prsentes par
Google et Amazon. Le rsultat, Cassandra, fut publi en projet libre sur Google Code en
2008, puis devint un projet Apache en mars 2009. Au fil des versions, Apache Cassandra
est devenu un produit trs intressant et reprsentatif de ce que le mouvement NoSQL peut
offrir de meilleur. Sur son site (http://cassandra.apache.org/), on apprend que Cassandra
est utilis par des acteurs comme Twitter, Reddit et Cisco, et que les installations de
production Apple reprsentent 75 000 nuds et 10 ptaoctets de donnes, et celles de
Netflix, 2 500 nuds, 420 traoctets de donnes et un billion2 doprations par jour.
Ironiquement, lorsque Facebook valua une nouvelle mthode de stockage pour ses
fonctionnalits de messagerie, les tests effectus avec un cluster de machines MySQL, un
cluster Cassandra et un cluster HBase les dcidrent choisir HBase, principalement pour
des raisons de facilit de monte en charge et de modle de cohrence de donnes
(http://www.facebook.com/notes/facebook-engineering/the-underlying-technology-of-
messages/454991608919). Mais ne vous mprenez pas, ce choix a t fait par Facebook en
2010. Depuis, Cassandra a vcu de trs importants changements, aussi bien en termes de
performance que darchitecture. Il nest pas sr que le mme test aujourdhui produirait
les mmes rsultats.
HBase et Cassandra sont des outils la fois proches et trs diffrents comme nous le
verrons plus en dtail dans ce livre.

DynamoDB
Amazon Dynamo, nous lavons vu, a inspir la cration de plusieurs moteurs NoSQL
comme Cassandra, Riak ou le projet Voldemort de LinkedIn. Lorsquil fut prsent en
2007, Dynamo ne pouvait pas tre utilis directement par dautres entreprises quAmazon.
Il tait mis en uvre dans les offres de services web dAmazon comme S3 (Simple
Storage Service), ce qui le rendait indirectement disponible pour les utilisateurs de ces
services. Toutefois, en janvier 2012, Amazon a dcid de rendre disponible son moteur
travers une offre cloud nomme DynamoDB (http://aws.amazon.com/fr/dynamodb/), qui
nest pas exactement le mme moteur que Dynamo, mais offre une technologie semblable.
Un exemple de table gr travers le service web dAmazon est reprsent sur la figure
suivante.

Figure 1-3
Interface dadministration de DynamoDB

Dans un article publi sur son blog en juin 2012


(http://www.allthingsdistributed.com/2012/06/amazon-dynamodb-growth.html), Werner
Vogels annonce que de tous les services dAmazon, DynamoDB est loffre ayant eu la
croissance la plus rapide, et quen juin 2012 elle avait dj dpass les prvisions
dAmazon pour lanne 2012. DynamoDB permet de grer des donnes trs rapidement et
de monter en charge travers le cloud dAmazon sans soccuper des dtails techniques ou
matriels. Il met disposition une API pour accder aux donnes laide de langages
comme Java, .NET ou PHP. Cest une tendance du NoSQL particulire : loffre cloud qui
reprsente les avantages de la simplicit et de loubli des contraintes matrielles, mais
comporte ses dsavantages, comme le stockage des donnes sur des serveurs appartenant
une socit tierce, qui plus est amricaine, et la dpendance des services qui ne sont pas
exempts de risques de dfaillance gnrale, comme on a pu lexprimenter quelques fois,
mme auprs des fournisseurs les plus srieux. On se souvient notamment quen fvrier
2013, Microsoft Azure fut indisponible durant deux jours cause de lexpiration dun
certificat SSL
Les volutions du Big Data
Hadoop a eu un succs fulgurant et il est toujours aujourdhui la bannire du Big Data.
Mais ce nest quune tape, dj marque historiquement par la sortie dune version
rarchitecture dHadoop, appele Hadoop Yarn ou MapReduce 2 (MRv2). Nous
reviendrons sur les dtails techniques de ce changement important, lessentiel tant que la
nouvelle architecture devient le socle pour un grand nombre de traitements distribus. L
o la gnration prcdente dHadoop tait limite un traitement de type Map Reduce en
mode batch, Hadoop Yarn permet de diversifier les types de traitement sur de trs larges
volumes de donnes, ce qui se rvle notamment trs utile de nos jours pour dvelopper
des systmes de traitement en quasi temps rel sur des architectures Big Data. Les outils
mergents du Big Data daujourdhui comme Apache Storm ou Apache Spark tournent sur
Hadoop Yarn. Nous allons bien sr parler dans cet ouvrage des importantes volutions de
ces technologies.

Le mouvement NoSQL est-il une avance ?


On la vu dans notre bref historique, lide de bases de donnes non relationnelles nest
pas nouvelle. En fait, le modle relationnel peut tre considr comme une innovation de
rupture qui a supplant les anciens modles. Est-ce que pour autant le mouvement NoSQL
reprsente un retour en arrire, comme certains peuvent le dire ? La victoire du relationnel
provient de son intelligence et de ses capacits rpondre aux dfis du moment, en
permettant doptimiser le stockage et le traitement des donnes une poque o les
capacits matrielles taient limites. Une base de donnes relationnelle est idale pour
assurer dexcellentes performances et lintgrit des donnes sur un serveur dont les
ressources sont par dfinition limites. Pour raliser cela, un moteur relationnel offre la
capacit de construire un modle de donnes, de lui adjoindre des structures physiques
comme des index, et dutiliser un langage dextraction, le SQL. Cela requiert beaucoup
defforts et de technicit dans la conception. Les SGBDR sont ns une poque o les
outils devaient tre compris et bien utiliss, et o le rythme de dveloppement tait plus
lent. Cette technicit se perd, les principes et limplmentation des SGBDR ne
senseignent pas assez dans les coles dinformatique, et les dveloppeurs qui sattaquent
la gestion des donnes nont pas suffisamment conscience des enjeux et des
mthodologies spcifiques ces outils.
De plus, lavnement de linformatique distribue a chang la donne : il ne sagit plus de
faire au mieux par rapport au matriel, mais dadapter les contraintes logicielles aux
possibilits dextension offertes par la multiplication des machines. Et cela provoque un
effet dentranement. La distribution permet laugmentation du volume des donnes, et
laugmentation du volume des donnes entrane un besoin accru de distribution. On sait
tous que 90 % du volume de donnes actuelles a t cr durant les deux dernires annes.
Une tude dEMC (http://france.emc.com/index.htm, lune des grandes entreprises du
stockage et du cloud) en 2011 a prvu une multiplication par cinquante du volume de
donnes informatiques entre 2011 et 2020. On nest videmment plus du tout dans le
domaine daction des bases de donnes relationnelles, en tout cas pas des SGBDR
traditionnels du march actuel.
Lune des expressions les plus souvent prononces par les acteurs du NoSQL est Web
scale. Un moteur NoSQL est conu pour rpondre des charges de la taille des besoins du
Web. Les besoins ont chang, les types de donnes manipules ont aussi volu dans
certains cas, de mme que les ressources matrielles.
Les besoins se sont modifis lorsque les sites web dynamiques ont commenc servir des
millions dutilisateurs. Par exemple, les moteurs de recherche doivent indexer des
centaines de millions de pages web et offrir des capacits de recherche plein texte
sophistiques et rapides. Ces donnes sont semi-structures, et on ne voit pas bien
comment on pourrait utiliser un moteur relationnel, qui impose des types de donnes
strictes et atomiques, pour raliser de telles recherches.
larrive dune nouvelle technologie, la tendance humaine est de rsister au changement
si la technologie actuelle est fermement ancre, ou au contraire de senthousiasmer au-del
du raisonnable si on nest pas familier avec lexistante, ou si on ne laime pas. Le
mouvement NoSQL constitue une avance ds lors que lon sait en profiter, cest--dire
lutiliser bon escient, en comprenant sa nature et ses possibilits. Cest justement le but
de cet ouvrage. Les capacits de stockage, les besoins de volumtrie, le dveloppement
rapide, les approches orientes service, ou encore lanalyse de donnes volumineuses sont
autant de paramtres qui conduisent lmergence dune nouvelle faon, complmentaire,
de grer les donnes.

La nbuleuse NoSQL
Aujourdhui, le mot NoSQL est connu de presque tous les informaticiens. Ce mouvement
a en effet vcu une nette progression au cours de la dernire dcennie. la parution de la
premire dition de ce livre, son utilisation tait encore rserve quelques entreprises
innovantes. Dsormais, le mouvement est bien enclench, et quelques socits de services
franaises se spcialisent dj dans le NoSQL. De nombreuses grandes socits,
notamment celles prsentes sur le Web ou dans le domaine des tlcommunications, ou
encore certains services publics, sinterrogent et recherchent des techniques leur
permettant de monter en charge ou de trouver des solutions leurs problmes de
traitement de donnes volumineuses. Nous en verrons un exemple dans le chapitre 16
prsentant une tude de cas. Mais, sous la bannire NoSQL, les choix techniques et les
acteurs sont divers. Ce nest pas du tout la mme chose que de chercher traiter en un
temps raisonnable des centaines de traoctets de donnes, ou de vouloir optimiser un
traitement de donnes en mmoire. Les outils sont donc parfois assez diffrents. Ils restent
nanmoins gouverns par quelques principes communs, ce qui permet de les regrouper
sous le terme de NoSQL.

Tentatives de classement
Avant de voir ce qui regroupe ces outils, essayons dabord de les distinguer. Quels sont les
grands groupes de moteurs NoSQL, et comment les classer ?

Classement par usage


Nous pouvons dabord tenter de les diffrencier suivant leur usage, cest--dire selon le
type de problmatique auquel ils rpondent. Nous en avons identifi quatre, que voici.
Amlioration des performances : certains moteurs NoSQL ont pour but daugmenter au
maximum les performances de la manipulation des donnes, soit pour offrir un espace
de cache en mmoire intermdiaire lors du requtage de SGBDR, soit en tant que SGBD
part entire, quil soit distribu ou non. Cet objectif est gnralement atteint par trois
mcanismes : lutilisation de la RAM et nous parlons donc de bases de donnes en
mmoire, la simplification du modle de donnes en paires cl-valeur et la distribution
du traitement sur les nuds dun cluster.
Assouplissement de la structure : pour saffranchir de la rigidit du modle relationnel,
les moteurs NoSQL simplifient la plupart du temps la structure des donnes (utilisations
de schmas souples comme le JSON, relchement des contraintes, pas dintgrit
rfrentielle entre des tables, pas de schma explicite au niveau du serveur).
Structures spcifiques : certains moteurs NoSQL sont ddis des besoins spcifiques,
et implmentent donc une structure et des fonctionnalits focalises sur un cas
dutilisation. Citons par exemple les moteurs orients graphes, ou les moteurs de
recherche plein texte qui offrent galement des fonctionnalits proches dun SGBD,
comme Apache Solr ou ElasticSearch.
Volumtrie : lun des aspects importants des moteurs NoSQL est leur capacit monter
en charge. Cest sans doute mme la raison premire de la cration du mouvement
NoSQL. Supporter des volumtries importantes passe par une distribution du stockage et
du traitement. Cest une distinction importante que nous approfondirons par la suite.
Hadoop est un systme de distribution du traitement colocalis avec un systme de
distribution de stockage. La distribution du traitement est trs importante dans un
contexte analytique et dans la plupart des applications Big Data. Le stockage distribu
est soit ralis par des fichiers plats sur un systme de fichiers distribus, soit par un
moteur de base de donnes distribu comme Cassandra ou Hbase, conu pour
fonctionner sur un large cluster de machines.
La distribution peut tre centralise ou dcentralise. Les systmes centraliss, qui
sinspirent souvent de Google, comportent un matre qui coordonne le stockage et
laspect transactionnel. Les systmes dcentraliss mettent chaque nud au mme
niveau, ce qui implique que chaque nud comporte un gestionnaire de donnes et un
gestionnaire de cluster, de faon pouvoir assurer la gestion des donnes bien sr, mais
aussi pour connatre et maintenir la topologie du cluster, et pouvoir rpondre aux
requtes des clients.
La figure suivante reprsente une carte de ces diffrents types dusage.
Figure 1-4
Les types dusage des moteurs NoSQL

Classement par schma de donnes


On peut aussi rpertorier les moteurs SQL par le schma ou la structure des donnes quils
manipulent. On distingue dans ce cas cinq modles.
Paires cl-valeur : les moteurs NoSQL les plus simples manipulent des paires cls
valeur, ou des tableaux de hachage, dont laccs se fait exclusivement par la cl. Il sagit
de moteurs en mmoire comme Redis ou de systmes distribus inspirs de Dynamo,
comme Riak. Ces moteurs offrent des fonctionnalits simplifies, souvent une moins
grande richesse fonctionnelle, en termes de requtes par exemple, et dexcellentes
performances grce leur modle daccs simplifi. Un systme de paires cl-valeur est
relativement facile implmenter : le pattern daccs par la cl ne ncessite pas de
moteur de requte complexe, et ce point dentre unique permet de soigner les
performances.
Les moteurs orients documents : le format de srialisation et dchange de donnes le
plus populaire est aujourdhui le JSON (JavaScript Object Notation). Il permet
dexprimer un document structur qui comporte des types de donnes simples, mais
aussi des listes et des paires cl-valeur, sous une forme hirarchique. Il est idal pour
reprsenter des donnes structures ou semi-structures. Il est donc logique de voir
apparatre des moteurs dont le format natif de stockage est le JSON. Cest le cas du trs
populaire MongoDB, mais aussi de CouchDB ou Couchbase Server. La nuance entre
moteurs paires cl-valeur et moteurs orients documents a tendance sestomper, parce
quau fur et mesure de leur volution, les premiers intgrent souvent un support du
JSON. Cest notamment le cas avec Riak qui depuis sa version 2 supporte lindexation
secondaire, donc sur des documents JSON dans la partie valeur de ses donnes.
Les moteurs orients colonnes : inspirs par Google BigTable, plusieurs moteurs
NoSQL implmentent une structure proche de la table, dont nous avons dj parl et que
nous avons dfinie comme une table de hachage distribue. Contrairement aux moteurs
orients documents, les donnes sont ici clairement reprsentes en lignes et spares
par colonnes. Chaque ligne est identifie uniquement par une cl, ce quon appelle dans
le modle relationnel une cl primaire, et les donnes de la ligne sont dcoupes dans
des colonnes, ce qui reprsente un niveau de structuration plus fort que dans les deux
modles prcdents. Plus utiliss pour des volumtries importantes, Cassandra ou Hbase
appartiennent cette catgotrie de moteurs.
Index invers : un index invers est une correspondance entre un terme, ou du contenu,
et sa position dans un ensemble de donnes, par exemple un document ou une page web.
Google utilise un index invers pour rpondre aux recherches sur son moteur. Il existe
des moteurs de recherche sur document quon apparente au mouvement NoSQL, comme
ElasticSearch ou Solr. Ils sont tous deux bass sur Lucene, le moteur dindexation en
index invers libre. Pourquoi les considrer comme des moteurs de bases de donnes ?
Parce que par-dessus Lucene, ils permettent de manipuler une structure JSON, de la
chercher et de la restituer. Cest pratique, parce que cela permet lutilisateur de
travailler avec une structure de donnes semblable un moteur orient documents, et de
profiter dexcellentes capacits de requtage grce au moteur de recherche.
Structures particulires : il nous reste juste regrouper les moteurs NoSQL qui ne
rentrent pas dans les catgories prcdentes, comme les moteurs orients graphe, qui
utilisent des reprsentations de donnes particulires et des mthodes de stockage
natives.

Peut-on trouver des points communs entre les moteurs


NoSQL ?
Avec lvolution des moteurs NoSQL, il devient pratiquement impossible de trouver des
points communs qui runissent tous ces moteurs et qui donnent un sens taxinomique au
terme NoSQL lui-mme. Certaines caractristiques sont prsentes dans presque tous les
moteurs mais il demeure toujours des exceptions. Voici quelques-uns de ces points
communs.
Le schma implicite. Alors que dans les moteurs relationnels, le schma des donnes
doit tre prdfini explicitement au niveau du serveur, dans la quasi-totalit des moteurs
NoSQL, le moteur ne contrle pas le schma des donnes et cest lapplication cliente
de structurer correctement ce quelle veut manipuler dans la base de donnes. Nous
verrons cela plus en dtail dans la suite de louvrage, mais il y a aujourdhui un contre-
exemple de taille : Cassandra qui, partir de sa version 2 sortie en 2014, impose un
schma fort, prdfini au niveau du serveur.
Labsence de relation. Que ce soient des tableaux ou des collections, les ensembles de
donnes stockes dans les moteurs NoSQL nont pas de relations les unes avec les
autres, linverse dun un moteur relationnel comme son nom lindique. Vous ne pouvez
donc pas crer de rfrence au niveau du serveur entre un lment dune collection et
plusieurs lments dune autre collection. Aucun mcanisme ne le permet. Chaque
collection est donc indpendante et cest un critre important pour assurer une
distribution facilite des donnes. On peut trouver quelques contre-exemples structurels
ou fonctionnels : ainsi, les moteurs orients graphe implmentent ncessairement des
relations entre les nuds, cest lexemple structurel ; et des moteurs de requte pour le
Big Data, comme Hive, permettent dexprimer dans la requte des clauses de jointure,
quils vont rsoudre derrire le rideau en requtant les diffrents ensembles de donnes,
cest lexemple fonctionnel.
Le langage SQL. Malheureusement pour le nom NoSQL lui-mme, labsence de
langage SQL nest pas du tout un critre de reconnaissance des moteurs NoSQL. De
nombreux moteurs SQL implmentent maintenant un langage dclaratif proche du SQL
pour la manipulation des donnes : CQL en Cassandra, N1QL dans Couchbase Server,
par exemple.
Le logiciel libre. Nous lavons vu, beaucoup de bases NoSQL sont des logiciels libres, et
participent au mouvement du libre. Le logiciel libre a maintenant prouv ses qualits.
Une grande partie des serveurs prsents sur Internet tournent sur des environnements
totalement libres, Linux bien sr, mais aussi Apache, Tomcat, nginx, MySQL et tant
dautres. Le libre nest plus synonyme damateurisme, et mme Microsoft supporte de
plus en plus le libre, travers des dveloppements comme les pilotes PHP et ODBC sur
Linux pour SQL Server, le support de Linux sur le cloud Azure, etc. Certaines
entreprises comme Facebook, ou pour rester franais, Skyrock (voir ltude de cas
chapitre 16), ont la culture du libre et mettent disposition de la communaut leurs
dveloppements internes, sans parler des contributions quils font, financirement ou en
temps de dveloppement aux grands projets libres. Le mouvement NoSQL est donc
naturellement un mouvement du logiciel libre. Les diteurs de SGBD traditionnels,
pousss par lengouement NoSQL, ont des attitudes diverses sur le sujet. Oracle, par
exemple, propose un entrept de paires cl-valeur distribu nomm simplement Oracle
NoSQL Database
(http://www.oracle.com/technetwork/products/nosqldb/overview/index.html), avec une
version communautaire librement tlchargeable et une version Entreprise qui
comportera des amliorations payantes. Cest aussi le choix dacteurs du monde NoSQL
comme Basho, qui dveloppe Riak, ou 10gen avec MongoDB. Des versions Entreprise
ou des services additionnels sont payants. Dautres moteurs sont totalement libres,
comme HBase ou Cassandra. Un certain nombre de socits se sont cres autour de ces
produits pour vendre des services, de lhbergement ou de la formation, telles que
Datastax (http://www.datastax.com/) pour Cassandra ou Cloudera pour la pile Hadoop,
HDFS et HBase. Microsoft a annonc vouloir supporter Hadoop sur Windows et Azure
dbut 2012, notamment en relation avec les fonctionnalits de dcisionnel de leur
moteur SQL Server. Le service sappelle maintenant HDInsight
(http://www.microsoft.com/sqlserver/en/us/solutions-technologies/business-
intelligence/big-data.aspx). On a lhabitude de ces noms trs marketing de la part de
Microsoft.
Pour toutes ces raisons et pour leur excellente intgration dans les environnements de
dveloppement libre, les moteurs NoSQL sont maintenant un choix intressant de
gestion des donnes pour des projets de dveloppement bass sur des outils libres, dans
des langages comme PHP ou Java, et dans tous types denvironnements, galement sur
les clouds de Microsoft (par exemple, une installation de MongoDB est disponible pour
Windows Azure) ou dAmazon.
2. Soit un trillion en anglais.
2
NoSQL versus SQL : quelles diffrences ?

Sil y a du NoSQL qui signifie aujourdhui, aprs quelques hsitations,


diplomatiquement Not Only SQL , cela veut dire quil y a donc aussi du SQL. Quelle est
alors la diffrence entre les deux approches ? Sont-elles si loignes lune de lautre et
rellement ennemies ? En quoi le mouvement NoSQL scarte-t-il du modle relationnel
et quels sont les choix techniques qui le caractrisent ? Voici les questions auxquelles nous
allons tenter de rpondre dans ce chapitre.

Les principes du relationnel en regard du NoSQL


Dans le chapitre prcdent, nous avons vu do venait historiquement le modle
relationnel, et le rle important qua jou Edgar Codd, son crateur, dans lhistoire des
bases de donnes. Voyons maintenant brivement quelles sont les caractristiques
techniques des SGBDR, ce qui nous permettra de mieux comprendre la diffrence
apporte par le mouvement NoSQL.
Tout dabord, le modle relationnel est bas sur le prsuppos quun modle
mathmatique peut servir de base une reprsentation des donnes dans un systme
informatique. Cela se retrouve dans la conception mme des entits que sont les tables des
bases de donnes relationnelles. Elles sont reprsentes comme des ensembles de donnes
et reprsentes sous forme de table. Il y a une sparation totale entre lorganisation logique
des donnes et limplmentation physique du moteur. Les donnes sont trs structures :
on travaille dans le modle relationnel avec des attributs fortement typs et on modlise la
ralit pour la faire entrer dans ce modle relativement contraignant. Ce systme offre
lavantage de pouvoir ensuite appliquer des oprations algbriques et logiques sur ces
donnes, mais en contrepartie force des donnes parfois plus complexes se plier cette
structure prdfinie.
Cette approche, qui prend sa source dans des modles thoriques et soccupe ensuite de
limplmentation physique, est totalement diffrente du mouvement NoSQL qui se base
sur des exprimentations pratiques pour rpondre des besoins concrets. Nous avons vu
lhistoire de Dynamo dAmazon, o le dveloppement a t orient vers la rsolution
dune problmatique particulire laide dun certain nombre de technologies dj
existantes et dont le mariage nallait pas de soi de prime abord. Beaucoup de moteurs
NoSQL utilisent maintenant les technologies de Dynamo parce quAmazon a dmontr
que ces solutions taient viables pour la simple et bonne raison que cet outil est utilis
avec succs sur le panier dachat du site Amazon. Il sagit donc ici plus dun travail
dingnieur que dun travail de chercheur ou de mathmaticien.
Les structures de donnes
Entre le relationnel et le NoSQL, il y a des conceptions fondamentalement diffrentes de
la structure des donnes. En fait, dans le NoSQL lui-mme, il existe diffrentes faons de
considrer la donne.
Le modle relationnel se base sur une structuration importante des donnes. Les
mtadonnes sont fixes au pralable, les attributs sont fortement typs, et selon les
principes dicts par Codd, la normalisation correcte des structures implique quil ny ait
aucune redondance des donnes. Les entits ont entre elles des relations, ce qui permet
davoir un modle totalement interdpendant.
Dans le modle relationnel, la mtaphore de la structure, cest le tableau : une suite de
lignes et de colonnes avec sur la premire ligne, le nom des colonnes en en-tte. Cela
signifie que les mtadonnes font partie de len-tte et ne sont bien sr pas rptes ligne
par ligne. Cela veut dire galement que chaque donne atomique est stocke dans une
cellule, et quon peut la retrouver en indiquant le nom de la colonne et lidentifiant de la
ligne.
Nous avons vu dans le chapitre prcdent les diffrentes structures de donnes utilises
dans le monde NoSQL, comme les paires cl-valeur ou les documents JSON.

Lagrgat
Parlons un instant de lide dagrgation. Nous reprenons ici les ides de Pramod J.
Sadalage et Martin Fowler dans leur livre NoSQL Distilled 3, qui permettent bien de
comprendre les diffrences essentielles de structuration des donnes entre les bases de
donnes relationnelles et le NoSQL.
Les auteurs soulignent justement que cest un concept intressant pour comprendre les
structures des bases NoSQL. Lide provient dric Evans et de son livre Domain-Driven
Design4 sur la conception pilote par le domaine. Lun des concepts de cet ouvrage est
lagrgat, savoir une collection dobjets lis par une entit racine, nomme la racine de
lagrgat. Lagrgat permet de crer une unit dinformation complexe qui est traite,
stocke, change de faon atomique. De lextrieur, on ne peut faire rfrence lagrgat
que par sa racine. En termes de programmation, cest un concept intressant parce quil
permet dassurer lunit et lintgrit dun bloc dinformation en identifiant une racine, on
pourrait dire une cl, et en permettant la rfrence uniquement sur cette cl. Cest une
notion qui permet galement de modliser des lments quon trouve dans la ralit. Par
exemple, un magazine peut tre vu comme une unit, qui contient des pages, des articles,
des illustrations, un contenu riche et complexe, mais qui nexiste pas indpendamment du
magazine lui-mme. Pour y faire rfrence, vous vous rfrez au magazine. Pour lire un
article, vous devez prendre le magazine et louvrir. La racine reprsente donc le point
dentre ce bloc dinformation.
Une base de donnes oriente documents stocke des donnes sous forme dagrgats. Le
document JSON contient un bloc dinformation, une cl qui permet de lidentifier
uniquement dans la collection des documents, et la manipulation du contenu du document
se fait la base en extrayant le document du moteur pour le manipuler dans son intgralit
et le stocker nouveau dans sa totalit.
De ce point de vue, une base de donnes relationnelle ne structure pas du tout ses donnes
en agrgats. Toute la structure des tables et des relations est plat, et lorsque nous
effectuons une requte SQL, comme celle-ci :
SELECT
c.ContactId, c.Nom, c.Prenom, SUM(f.MontantHT) as TotalFactureHT,

COUNT(i.InscriptionId) as NbInscriptions

FROM Contact.Contact c
JOIN Inscription.Inscription i ON c.ContactId = i.ContactId

JOIN Inscription.InscriptionFacture inf ON i.InscriptionId = inf.InscriptionId

JOIN Inscription.Facture f ON inf.FactureCd = f.FactureCd


JOIN Stage.Session s ON i.SessionId = s.SessionId

GROUP BY c.ContactId, c.Nom, c.Prenom;

nous exprimons dans la requte un agrgat que nous formons partir des donnes des
tables. Nous prenons la dcision de partir dune table spcifique (dans ce cas, le contact) et
nous exprimons par les jointures lagrgat dont cette table est la racine (ici, on rcupre
ses inscriptions et le montant de ses factures). On peut donc, partir dun modle
relationnel, crer dynamiquement les agrgats souhaits partir de nimporte quelle
racine, de nimporte quel point dentre. La requte suivante retourne galement le
nombre dinscriptions et le montant des factures, mais cette fois-ci par rapport une
session de formation, donc en partant dune racine diffrente.
SELECT s.SessionId, s.DateDebut, SUM(f.MontantHT) as TotalFactureHT,
COUNT(i.InscriptionId) as NbInscriptions
FROM Stage.Session s

JOIN Inscription.Inscription i ON s.SessionId = i.SessionId


JOIN Inscription.InscriptionFacture inf ON i.InscriptionId = inf.InscriptionId
JOIN Inscription.Facture f ON inf.FactureCd = f.FactureCd;

Lagrgat est une unit dinformation qui va tre manipule par un programme. Cest
quelque chose qui sera exprim par exemple en un objet ou une collection dobjets dans
un langage orient objet.

La centralit de la donne
Cette souplesse du SGBDR lui permet de servir plusieurs besoins applicatifs. Comme
chaque application a besoin dun agrgat diffrent, la structure plate dune base de
donnes relationnelle permet de reconstituer les agrgats demands par chaque
application. Par exemple, une base de donnes de gestion dentreprise va permettre de
satisfaire les applications des diffrents services : la logistique, la comptabilit, la relation
client, ou la gestion des stocks, qui voudront manipuler les donnes par des agrgats sur
les commandes, les factures, lidentit du client, le produit.
En revanche, si lagrgat est dj form dans la structure de la base de donnes, comme
cest le cas dans un moteur orient documents, il sera plus enclin satisfaire un besoin
applicatif, mais pas tous.
Il y a donc dans les bases de donnes relationnelles une centralit plus forte de la donne
par rapport aux applications, et une seule base de donnes pourra tre le point de
convergence de plusieurs processus dapplication de lentreprise. Martin Fowler lexplique
de la faon suivante : les bases de donnes relationnelles sont des outils dintgration et ils
ont t utiliss en dveloppement comme tels. Cette capacit de centralisation a t
exploite par les projets informatiques pour faire converger les diverses applications client
vers un seul point.
Est-ce une bonne ou une mauvaise chose ? Un moteur de base de donnes est-il un outil
dintgration ? En tout cas, on a pris lhabitude de le considrer ainsi, et lorsquon
entreprend de choisir un moteur de base de donnes, on pense gnralement un seul
moteur pour rpondre tous les besoins.
Si on abandonne lide du moteur de base de donnes unique qui centralise les besoins de
toutes les applications, on peut alors choisir diffrents moteurs selon ses besoins, mais on
doit alors considrer la duplication des donnes, lchange et la transformation de ces
donnes, bref une couche supplmentaire dintgration, quil faut concevoir, dvelopper,
maintenir, avec les contraintes darchitecture, de dveloppement, de performances et bien
sr dintgrit. On se rapproche de la conception oriente services.

Les structures de donnes des moteurs NoSQL


La plupart des moteurs NoSQL manipulent des agrgats. Il y a bien sr des exceptions, et
les choses voluent. Autant vous le dire tout de suite : le monde NoSQL est un terrain en
pleine volution, soyez prt tout. Un contre-exemple vident est le groupe des moteurs
de bases de donnes orients graphe, structurs en nuds et en relations entre les nuds. Il
sagit doutils comme Neo4J. Ils ne sont pas du tout architecturs partir dune cl, de la
racine dun agrgat, et ils se rapprochent de ce point de vue des moteurs relationnels. Ils
sont galement difficiles distribuer. Cet exemple montre quil est difficile de gnraliser
des caractristiques dans les moteurs runis sous la bannire NoSQL.
Nous avons dj vu deux cas de structure : la structure cl-valeur et la structure oriente
documents. Il existe une autre grande catgorie, appele moteurs orients colonne. Nous
en parlerons plus loin, mais pour schmatiser, ces moteurs se basent sur la structure de
Google BigTable, et reproduisent une structure en apparence assez proche du modle
relationnel. En tout cas, ils reprennent la mtaphore de la ligne et des colonnes. Il y a donc
une structure plus formelle, plus contraignante que les autres moteurs. Mais dans les faits,
ce que vous stockez dans une colonne de ces bases de donnes nest pas typ, ni limit.
Vous avez beaucoup moins de contrainte. Et, concrtement, vous tes beaucoup plus
proche dun agrgat que dune table, parce que la cl revt une plus grande importance.
Nous nen disons pas plus ici, nous entrerons dans les dtails au chapitre 4.

Le modle et la ralit
Pour penser et schmatiser la ralit, nous avons besoin de modles : pour penser la
matire, nous avons bti un modle des atomes qui correspond de petits systmes
stellaires. Pour penser le dcoupage le plus lmentaire de la matire, il existe aujourdhui
une thorie des cordes, qui reprsente ces lments sous forme de filaments. Cela ne
correspond pas la ralit telle quon pourrait lobserver objectivement, cest simplement
un modle qui va nous permettre, grce une simplification et une adaptation, quelque
chose que nous pouvons saisir cognitivement et reprsenter. Mais videmment il ne faut
pas confondre ralit et reprsentation. Et parfois les reprsentations peuvent changer.
Nous avons dj signal quun changement de technologie provoque une tension tirant
dans deux directions : vers le conservatisme, et vers lattrait irrflchi du nouveau. Il y a
conservatisme en base de donnes parce quon a pris lhabitude dun modle dominant. Le
modle relationnel est juste un modle, ce nest pas une vrit objective et naturelle. Il
permet beaucoup de choses, mais il nest pas la vrit rvle et il nest pas infaillible. Il
est facile den dnigrer dautres juste parce quon a pris lhabitude dun modle. Dautre
part, le modle relationnel possde de nombreuses qualits, et il serait idiot de le
remplacer aveuglment par autre chose pour simplement satisfaire un got de la
nouveaut. En fait, le mouvement NoSQL nest pas une rvolution au sens politique du
terme : le remplacement dun ancien rgime par un nouveau. On sait en gnral que ce
type de radicalisme saccompagne dune forme daveuglement. Cest une rvolution plutt
copernicienne, dans le sens o la place dun modle hgmonique, qui nous oblige le
choisir en toutes circonstances, on obtient quelque chose de plus riche : le choix.

La modlisation
Lune des caractristiques les plus importantes du modle relationnel est justement les
relations, cest--dire le fait de modliser les donnes sous forme de tables relies entre
elles par des relations sur des cls. Cela implique une rflexion prliminaire quon appelle
justement modlisation et dont dpend largement la qualit du systme qui sera bti autour
de la base de donnes. Crer le modle dune base de donnes relationnelle est la premire
tape du dveloppement, lequel sera dautant plus facile et efficace que cette tape est
russie. En dautres termes, pour russir dans le monde relationnel, il est conseill de
veiller bien conduire ltape danalyse prliminaire. Le modle relationnel sintgre bien
dans un processus de dveloppement squentiel tel que le modle de la chute deau
(Waterfall Model), illustr sur la figure 2-1.

Figure 2-1
Le modle Waterfall

Ce modle bien connu implique que chaque tape du dveloppement logiciel soit
matrise et termine avant de passer ltape suivante. Cest pour cette raison que le
terme waterfall est employ : leau coule vers le bas, mais il ny a jamais de retour aux
tapes prcdentes. Il est assez clair que ce modle a montr ses nombreuses limites et
quil est de plus en plus abandonn de nos jours pour des mthodes dites agiles , qui
considrent le dveloppement comme un processus itratif, o chaque tape essaie dtre
suffisamment courte et souple pour pouvoir corriger rapidement les choix malheureux et
tre beaucoup plus flexible. Lironie de ce modle, utilis pendant des dcennies pour
conduire les projets informatiques, est que sa premire description formelle peut tre
trouve dans un article de Winston Royce intitul Managing the Development of Large
Software Systems ( Grer le dveloppement de systmes logiciels de grande taille ),
rdig pour une confrence ayant eu lieu en 1970 (le papier original est disponible
ladresse suivante :
http://www.cs.umd.edu/class/spring2003/cmsc838p/Process/waterfall.pdf). Le Waterfall
est prsent dans cet article comme un exemple de modle qui ne fonctionne pas.
Quarante ans plus tard, un grand nombre de projets informatiques continuent tre bass
sur ce type de procdures.
Lun des reproches faits aux SGBDR par le mouvement NoSQL est donc la rigidit du
modle et les difficults que pose sa ringnierie. Cela est d galement la structuration
forte des donnes. Dans un SGBDR, vous devez btir autant que possible toute la structure
avant de pouvoir travailler avec le contenu. Lorsque le contenu est vivant, il devient
ensuite difficile de modifier la structure. Pour cette raison, la plupart des moteurs de bases
de donnes NoSQL appliquent un modle sans schma (schema-less), o le schma des
donnes na pas vraiment besoin dtre fix lavance. Nous verrons ce que cela signifie
dans le chapitre 3 consacr aux choix techniques des moteurs NoSQL.

La rigidit du modle relationnel


La modlisation est certes une tape importante. Mais le procs en rigidit qui est fait au
modle relationnel est exagr. De nos jours, ajouter une colonne dans un moteur
relationnel nest pas trs difficile, et limpact sur lapplication cliente est nul si le
dveloppeur a bien fait son travail. La rigidit du modle relationnel est donc relative, et
les moteurs NoSQL ne sont pas miraculeusement prservs de ce type de problmatique.
Dune certaine faon, ce nest pas la faute du modle, mais de ses implmentations. La
modification dun modle relationnel est coteuse, mais changer des donnes stockes
dans une base NoSQL ne lest pas forcment moins. Si vous avez stock des centaines de
milliers de documents JSON qui mentionnent un code de produit, et que la structure de ce
code change on passe par exemple dun EAN 10 un EAN 13, comme cela sest produit
sur les ISBN (International Standard Book Number) pour le march du livre , vous serez
bien entendu oblig de modifier vos donnes comme vous auriez le faire dans un moteur
relationnel. Vous pouvez mme avoir plus de travail faire que dans un moteur
relationnel. Pour deux raisons :
beaucoup de moteurs NoSQL sont plutt des systmes de dpts de donnes qui nont
pas de concept de langage de manipulation ct serveur et de traitement efficace des
oprations sur des collections de donnes. Le traitement est souvent unitaire ;
il ny a en gnral pas de mcanisme dabstraction des structures de donnes semblables
aux vues.
Les choses voluent et continuent voluer. Les moteurs NoSQL sont la base des outils
simplifis, qui peu peu senrichissent fonctionnellement. Mais pour linstant le modle
relationnel est plus lgant et plus riche fonctionnellement sur bien des points.

Le partitionnement de donnes
Lun des problmes de la normalisation dans un SGBDR concerne la distribution des
donnes et du traitement. Si vous stockez des donnes qui ont un rapport entre elles,
comme des clients, des commandes, des factures, des lignes de facture, etc., dans des
tables diffrentes, vous rencontrerez un problme lorsque vous souhaiterez partitionner ces
donnes, les sharder 5. Vous devez alors vous assurer que les donnes en rapport les unes
avec les autres se trouvent sur le mme serveur, en tout cas si vous voulez raliser des
jointures du ct du serveur. Dans le cas contraire, vous devrez effectuer des changes
entre serveurs pour manipuler vos donnes. De ce point de vue, un stockage orient
documents, qui contient dans un document lintgralit des donnes correspondant la
requte effectuer, quitte gnrer une base de donnes finalement trs volumineuse
cause dun grand nombre de doublons de valeurs, prsente un certain nombre davantages.
Dans un modle o les donnes sont dcoupes, il reste possible de sassurer que les
diffrentes tables se partitionnent de faon localiser leurs relations, mais cela implique
une gestion manuelle des cls primaires et du sharding, ainsi que des techniques
spcifiques pour distribuer le plus galement possible des donnes entre nuds. Ce nest
donc pas une affaire simple et elle est difficile automatiser.
Toutefois, on ne peut argumenter de faon schmatique que le modle relationnel est non-
partitionnable et quil faut systmatiquement partir sur une solution NoSQL base sur une
agrgation. Les choses voluent et lavenir verra sans doute une plus grande tolrance au
partitionnement du modle relationnel. Lorsque nous parlerons du thorme CAP (voir
page 43), nous verrons quil est impossible davoir en mme temps une disponibilit
satisfaisante, une tolrance au partitionnement et une bonne cohrence des donnes. La
cohrence est une chose, les capacits relationnelles en sont une autre. Il y a aujourdhui
de nombreuses initiatives pour distribuer des moteurs relationnels : plusieurs initiatives
tournant autour de MySQL ou de MariaDB comme MySQL Cluster, des bases de donnes
dites NewSQL comme VoltDB ou NuoDB, et le plus impressionnant et mystrieux de
tous, le systme relationnel et transactionnel de Google amen remplacer son moteur
orient colonnes, Google Spanner.
Google F1
Depuis plusieurs annes, Google publie rgulirement des articles sur le dveloppement interne dun moteur de
base de donnes relationnelle compltement distribue. Notamment, en 2012, des ingnieurs de lentreprise ont
diffus un document intitul F1 - The Fault-Tolerant Distributed RDBMS Supporting Googles Ad Business
(http://research.google.com/pubs/pub38125.html) au SIGMOD, le Special Interest Group on Management of Data
de lACM. Plusieurs systmes importants de Google tant encore grs sur MySQL, le gant amricain a dvelopp
en interne un moteur compltement distribu pour le remplacer. Celui-ci supporte toutes les fonctionnalits
importantes dun SGBDR, avec un moteur de requte paralllis et la gestion des transactions, tout en sappuyant
sur un stockage compltement distribu. Les mises jour sont transactionnellement cohrentes, ce qui entrane une
latence plus importante dans les mises jour, compar leur prcdent systme sur MySQL, mais le document
explique quelle a t leur stratgie pour contourner ce problme. Google prsente F1 comme le mariage russi entre
les forces du NoSQL (la distribution) et les qualits, notamment transactionnelles, du SGBDR.

En bref, il existe maintenant des implmentations aussi bien que des recherches menes
pour permettre le partitionnement dun modle bas sur des relations. Aujourdhui, il
demeure beaucoup plus simple de distribuer des donnes non lies, mais cette situation
voluera peut-tre dans un avenir proche.

Le langage SQL
Le langage SQL est un langage dextraction de donnes, certes conu autour du modle
relationnel, mais il nest pas le modle relationnel lui-mme. SQL est un langage
principalement dclaratif, destin la manipulation de donnes et relativement proche du
langage naturel. Les bases de donnes du mouvement NoSQL nont pas vocation
sopposer ou sloigner du langage SQL, mais du modle relationnel. Ce sont les
implmentations courantes du modle relationnel qui comportent les limitations que les
bases NoSQL cherchent dpasser. On devrait donc appeler ce mouvement
NoRelational plutt que NoSQL.

Les qualits du langage SQL


Nous ne rsisterons pas citer une conclusion de Philip Greenspun, lun des pionniers du
dveloppement de sites web pilots par les donnes, dans un article de blog publi en 2005
et illustrant une requte SQL (http://blogs.law.harvard.edu/philg/2005/03/07/).
Regardez comme il est amusant de programmer du SQL. Trois lignes de code et vous
obtenez une rponse intressante []. Comparez cela du Java et du C, o taper sur votre
clavier jusqu ce que vos doigts se dtachent ne donne en gnral que peu de rsultats.
SQL, Lisp et Haskell sont les seuls langages de programmation que jai vus o on dpense
plus de temps rflchir qu taper.
Pourquoi alors vouloir sloigner du langage SQL si son expressivit offre un haut niveau
dabstraction et de puissance ? Sans doute pour deux raisons : exprimer une requte
correcte en SQL requiert justement plus de rflexion que de programmation. On peut
construire une requte SQL de manire itrative, bloc aprs bloc, mais ces blocs ne sont
pas des oprations, ce sont des lments de la demande. Bien travailler en SQL demande
de ne jamais perdre de vue la question qui est pose, et den examiner scrupuleusement
chaque mot. Cest rellement une autre faon de penser que celle qui est luvre dans
lcriture de code impratif. La seconde raison concerne ce quon appelle le dfaut
dimpdance objet-relationnel.

Le requtage dclaratif en NoSQL


Il y a des volutions rapides dans le NoSQL, et aussi du point de vue du langage de
requte. Depuis la premire dition de ce livre, plusieurs changements sont survenus vers
lintgration de langages de requte dclaratifs dans les moteurs NoSQL. Deux exemples :
Cassandra, pass en version 2, a remplac officiellement le langage de lAPI Thrift par
CQL (Cassandra Query Language), qui reproduit exactement la syntaxe du langage SQL.
De son ct, Couchbase Server a introduit dans sa version 3 un langage dclaratif nomm
N1QL (prononcer nickel ) qui utilise une syntaxe SELECT trs proche du SQL et permet
mme dapprocher du concept de la jointure avec des instructions comme NEST et UNNEST.
Autre exemple plus pouss, dans lanalytique interactive avec Hadoop, des outils comme
Hive ou Spark proposent une syntaxe SQL qui tente de se rapprocher de la norme SQL.
HiveQL inclut ainsi une large part de la syntaxe des jointures dfinie dans la norme, avec
jointures internes, externes, les CROSS JOIN et mme une syntaxe SEMI JOIN pour implmenter
dans la clause de jointure la smantique du mot-cl EXISTS. Lune des restrictions de
HiveQL est de se limiter une quijointure : on ne peut crire des clauses de jointure qui
reposent sur autre chose quune galit. Mais cest de toute faon la grande majorit des
cas dutilisation.
Le terme NoSQL devient donc de moins en moins valide, et dans peu de temps, le seul
critre commun subsistant pour essayer de donner une dfinition gnrale des moteurs
NoSQL, savoir quils nutilisaient pas de paradigme relationnel, risque de devenir
obsolte.

Mfiez-vous des comparaisons


Une chose assez vidente, mais qui est hlas rarement mise en avant dans les
comparaisons faites par les dfenseurs du NoSQL avec les moteurs relationnels, cest que
MySQL est souvent utilis comme point de comparaison. La plupart des entreprises qui
ont dvelopp des moteurs NoSQL ont un esprit open source : Google, Facebook, Twitter,
LinkedIn utilisent tous intensivement MySQL ou MariaDB. Twitter par exemple a
dvelopp en 2011 une couche de sharding sur MySQL nomme Gizzard.
Le problme, cest que MySQL nest pas le meilleur moteur relationnel. Il souffre dun
certain nombre de problmatiques qui rendent son utilisation intensive et ses performances
dlicates, et on ne peut pas le prendre comme modle dune critique objective de tous les
moteurs relationnels. En voici quelques preuves.
Beaucoup de dfenseurs du mouvement NoSQL avancent que lune des forces de ces
moteurs est labsence de jointures, et que ce sont les jointures qui provoquent de forts
ralentissements dans les moteurs relationnels. la base, la jointure nest pas un problme
dans un bon SGBDR. Elle se fait en gnral entre la cl primaire et une cl trangre, et si
toutes les deux sont indexes, cela quivaut une recherche de correspondance travers
deux index. Si la cardinalit du rsultat est faible, cest--dire si la correspondance touche
un petit nombre de lignes, les algorithmes de jointure des moteurs relationnels offrent
dexcellentes performances. En fait, les performances sont meilleures que celles dun
moteur NoSQL, parce que ce qui cote le plus cher dans un moteur de base de donnes ce
sont les entres-sorties. partir du moment o le modle relationnel limine la
redondance, le volume de donnes parcourir pour rsoudre la requte est moindre que
dans un moteur NoSQL, et donc les performances sont meilleures.
Mais, historiquement, MySQL gre trs mal les jointures. Jusqu la version 5.6 de
MySQL et les versions 5.3 et 5.5 de MariaDB, le seul algorithme disponible est la boucle
imbrique. Cest un algorithme valable sur des petits volumes et qui devient totalement
contre-performant sur des volumtries plus importantes. Les moteurs relationnels
commerciaux implmentent deux autres algorithmes qui sont la jointure de fusion (merge
join ou sort-merge join) et la jointure de hachage (hash join). Notamment, la jointure de
hachage est beaucoup plus performante sur des gros volumes.
Donc MySQL nest vraiment pas un bon point de comparaison pour les jointures
volumineuses, car dautres moteurs relationnels sen sortent beaucoup mieux. Mais il est
clair que lorsquon veut effectuer des jointures sur des volumes importants pour des
requtes analytiques o le nombre de correspondances est important, un moteur
relationnel va montrer ses limites et le NoSQL arrive la rescousse.
Autre exemple, on a abord le sujet de la rigidit du modle. Si vous utilisez MySQL,
vous pouvez facilement avoir limpression quil est trs pnible de modifier le schma de
vos tables. Jusqu la version 5.6 de MySQL, un certain nombre de modifications de
tables taient effectues hors ligne . Beaucoup de commandes ALTER TABLE, au lieu
deffectuer simplement la modification dans la structure de la table, dclenchaient derrire
le rideau la cration dune nouvelle table, suivie de la copie de toutes les donnes de
lancienne table dans la nouvelle, puis de la suppression de lancienne table et enfin du
renommage de la nouvelle. Vous imaginez leffet sur des tables volumineuses dans un
environnement fortement multi-utilisateurs. Or, bien entendu, les SGBDR ne fonctionnent
pas tous ainsi.
On voit galement souvent des donnes chiffres de volumtrie. Par exemple, on lit
quune table comportant un million de lignes deviendrait impossible grer dans un
moteur relationnel. En ralit, un moteur SQL est capable de grer correctement des tables
qui comportent des centaines de millions de lignes, voire des milliards de lignes, partir
du moment o les recherches quon effectue sur ces tables sont slectives et utilise de bons
index. Dans le terme Big Data, Big veut dire vraiment Big.

Le dfaut dimpdance
Lune des rugosits du langage SQL est ce que les Anglo-Saxons appellent le dfaut
dimpdance (impedance mismatch) objet-relationnel.
Ce terme est un emprunt llectricit. Limpdance est, pour simplifier, une opposition
faite par un circuit au passage dun courant lectrique. Optimiser limpdance consiste
diminuer cette rsistance et donc transfrer une nergie de faon optimale. Par dfaut
dimpdance, les crateurs du terme voulaient signifier que le passage du relationnel
lobjet seffectue avec une perte dnergie et une rsistance trop forte. Prenons lexemple
dun code PHP qui appelle une requte SQL pour faire une recherche dans MySQL :
<?php

mysql_connect(localhost,root,********);

mysql_select_db(********);
$nom = $_REQUEST[nom];

$prenom = $_REQUEST[prenom];

$ville = $_REQUEST[ville];
$pays = $_REQUEST[pays];

$sexe = $_REQUEST[sexe];

$age = $_REQUEST[age];
$where = "";

$where .= isset($nom) ? (isset($where) ? " OR " : " WHERE " )."( nom = $nom) " :

")"
$where .= isset($prenom) ? (isset($where) ? " OR " : " WHERE " )."( prenom =

$prenom) " : ")"


$where .= isset($ville) ? (isset($where) ? " OR " : " WHERE " )."( ville = $ville)

" : ")"
$where .= isset($pays) ? (isset($where) ? " OR " : " WHERE " )."( pays = $pays)

" : ")"
$where .= isset($sexe) ? (isset($where) ? " OR " : " WHERE " )."( sexe = $sexe)
" : ")"

$where .= isset($age) ? (isset($where) ? " OR " : " WHERE " )."( age = $age) " :

")"
$sql = "SELECT nom, prenom, ville, pays, sexe, age

FROM Contact

$where
ORDER BY nom, prenom DESC ";

$req = mysql_query($sql) or die(Erreur SQL !<br />.$sql.<br />.mysql_error());


$data = mysql_fetch_array($req);

mysql_free_result ($req); ?>

Ici, nous devons construire une chane pour btir la requte SQL qui sera envoye telle
quelle au serveur. Afin de btir la meilleure chane possible, nous testons la valeur de
chaque paramtre pour viter dintroduire dans la requte des critres de recherche trop
nombreux, ce qui diminuerait les performances de la requte. Le code PHP est reconnu par
linterprteur, cest du vrai code. La chane SQL, quant elle, nest rien dautre ce
niveau quune chane. Elle ne sera reconnue que du ct du serveur. Il ny a pas de relle
interaction entre le code PHP et le code SQL.
Il y a effectivement quelque chose de frustrant que lon se place dun ct ou de lautre de
la lorgnette. Si on est un dveloppeur objet, on souffre de devoir sortir du modle objet
pour interroger la base de donnes. Du point de vue du dfenseur du langage SQL,
llgance de sa syntaxe lui permet dexprimer la complexit dune faon trs sobre, et
rsume des oprations complexes en peu de mots. Les langages objet restent tributaires
dune logique procdurale, o chaque opration doit tre exprime. Lexcution dun code
procdural est aveugle. Pas de raisonnement ncessaire, le code sexcute comme
demand. Un langage dclaratif comme le SQL est soutenu par un moteur doptimisation
qui dcide, en vrai spcialiste, de la meilleure mthodologie pour obtenir les rsultats
dsirs. Il sagit de deux approches trs diffrentes qui naturellement sexpriment par des
langages qui ne fonctionnent pas au mme niveau. Cela conduit rassembler tant bien que
mal deux types doprations trs diffrentes dans le mme code.
Pour traiter ce dfaut dimpdance, on peut maquiller lappel au SQL en lencapsulant
dans des objets qui vont faire office de gnrateur de code SQL. Les frameworks de
mapping objet-relationnel (Object-Relational Mapping, ORM) dissimulent ce travail en
automatisant la cration de classes pour les tables de la base de donnes, les lignes tant
reprsentes par des instances de ces classes. La thorie des gnrateurs de code est
intressante, mais en pratique le langage SQL est riche et complexe, et il est impossible
dautomatiser lgamment lcriture dune requte qui dpasse les besoins lmentaires
dextraction et de modification. Les requtes gnres par des outils comme Hibernate ou
Entity Framework sont par la force des choses gnriques et grossires, et ne permettent
pas de dvelopper toute la puissance du SGBDR. En fait, les requtes gnres sont trs
souvent bancales et disgracieuses et posent des problmes de performance. De plus, les
ORM dplacent une partie du traitement des donnes vers le client et se privent ainsi des
grandes capacits des moteurs relationnels manipuler et extraire des ensembles.

Pas de dfaut dimpdance en NoSQL ?


Est-ce que les moteurs NoSQL corrigent cette problmatique, si tant est quelle en soit
une ? Oui, dune certaine faon. Mme si certains moteurs NoSQL offrent un langage de
requte dclaratif, il est encapsul dans un pilote adapt chaque langage client. Voici un
exemple de requte vers MongoDB partir dun code PHP. Nous essayons de reproduire
quelque chose de semblable notre exemple MySQL.
<?

$mongo = new Mongo(mongodb://localhost:27017, array("timeout" =>

2000));
$db = $mongo->selectDB(CRM);
$db->Contact->find(

array($or => array(


array(nom => $nom),
array(prenom => $prenom),

array(ville => $ville),


array(pays => $pays),

array(sexe => $sexe),


array(age => $age)
)),

array (nom, prenom, ville, pays, sexe, age)


);
?>

Ici, bien sr, la requte utilise des objets propres au pilote MongoDB pour PHP dvelopp
par MongoDB Inc. Les critres sont envoys sous forme de double tableau, cest ensuite
MongoDB de se dbrouiller avec a, par exemple en utilisant un index secondaire sil est
prsent. Au passage, la stratgie dexcution est visible dans MongoDB en utilisant la
mthode explain, comme ceci :
$db->Contact->find(

array($or => array(

)),
array (nom, prenom, ville, pays, sexe, age)

)->explain();

Dautres moteurs, comme CouchDB, offrent une interface REST (Representational State
Transfer, voir le chapitre 3 consacr aux choix techniques du NoSQL). Envoyer une
requte REST et envoyer une requte SQL sont deux actions assez similaires : il faut
gnrer une URI avec des paramtres. La diffrence est quune URI est plus facile
gnrer quune requte SQL, et de nombreuses bibliothques existent pour tous les
langages clients qui permettent dexprimer les paramtres sous forme de table de hachage
ou de tableau, par exemple. Voici un exemple de gnration dune requte REST en
Python :
import urllib
import urllib2

url = http://localhost:5984
params = urllib.urlencode({

nom: nom,
prenom: prenom,
ville: ville,

pays: pays,

sexe: sexe,
age: age)

})

response = urllib2.urlopen(url, params).read()

Dautres moteurs supportent une interface Thrift, qui est une API daccs que nous
dtaillerons dans le chapitre 3.

Les ORM pour NoSQL


Les instructions dextraction des moteurs NoSQL sont simplifies : on est loin de la
complexit du langage SQL. De plus, les performances ne dpendent pas la plupart du
temps de la syntaxe des requtes, mais de la distribution du traitement. Il est donc
beaucoup plus facile de concevoir des gnrateurs de code. Mme si ce nest pas un
besoin qui sest fait sentir avec force, cest une demande de beaucoup dquipes de
dveloppement habitues cette manire de travailler, et il existe des bibliothques pour
les moteurs NoSQL les plus importants, par exemple avec MongoDB, mongoose pour
Node.JS ou mongoengine pour Python.

Les objets et le relationnel


Une autre rflexion frquemment rencontre dans le monde NoSQL compar au modle
relationnel est le rapport la ralit des donnes, en tout cas au modle tel quon le
btit dans lapplication cliente, en gnral sous forme dobjets. Lapplication cliente
organise ses donnes sous forme dobjets et se trouve oblige de dcomposer ces objets
pour les stocker dans des tables diffrentes. Mais les deux modles sont-ils si diffrents ?
Une bonne organisation des classes permet presque de respecter les trois premires formes
normales : chaque objet est une entit distincte dont les proprits reprsentent des
attributs qui se rapportent strictement la classe, et les classes entre elles entretiennent des
relations avec diffrentes cardinalits, travers des collections dobjets. Srialiser en un
document une classe et ses collections dobjets lis dans un document JSON nest donc
pas plus logique que de le faire dans des tables distinctes. Au contraire, lun des avantages
du modle relationnel est de permettre une grande conomie de stockage et une
reprsentation trs logique des donnes, de faon offrir tous les traitements et toutes les
utilisations possibles de ces donnes. De plus, il ny a pas de justification logique
conserver les donnes telles quelles sont manipules par un langage client.
Cest comme si quelquun vous disait que les dictionnaires devraient tre organiss en
phrases compltes, par ordre du sujet, puisque cest par le sujet que la phrase commence,
et ceci parce que tout le monde parle ainsi. Le dictionnaire est organis par ordre
alphabtique de mots, parce que le but dun dictionnaire est dy puiser lun aprs lautre
les vocables qui composeront les phrases, lesquelles sont de la responsabilit du locuteur,
et pas du dictionnaire.

Les NULL
Une autre critique porte aux SGBDR concerne les NULL. Du fait de la prdfinition dun
schma rigide sous forme de table, ou chaque colonne est prdfinie, un moteur
relationnel doit indiquer dune faon ou dune autre labsence de valeur dune cellule.
Ceci est ralis grce au marqueur NULL, qui est un animal un peu spcial dans le monde du
SGBDR. Au lieu de laisser la cellule vide, on y pose un marqueur, NULL, qui signifie valeur
inconnue. Le raisonnement est le suivant : laisser une chane vide dans la cellule indique
une valeur, savoir vide . Le marqueur NULL indique clairement labsence de valeur, ce
nest donc pas une valeur. Ceci dit, selon les implmentations, ce marqueur NULL cote un
petit peu en stockage. Une autre problmatique du NULL est sa gestion complique dans le
langage SQL. Dans la mesure o il ne sagit pas dune valeur, le marqueur NULL ne peut pas
tre compar, par exemple dans un critre de filtrage (clause WHERE) qui est valu vrai ou
faux. Il impose la gestion dune logique trois tats : vrai, faux et inconnu. Ainsi, la
requte suivante ne retournera pas les lignes dont le titre est NULL :
SELECT *

FROM Contact
WHERE Titre = Mme OR Titre <> Mme;

car le NULL ne pouvant se comparer, il nest ni gal Mme , ni diffrent, il est


simplement inconnu. Il faut donc chaque fois penser grer une logique trois tats de la
faon suivante :
SELECT *
FROM Contact
WHERE Titre = Mme OR Titre <> Mme OR Titre IS NULL;

Les moteurs NoSQL amnent de la souplesse dans cette conception. Dans les moteurs
orients documents ou paires cl-valeur, il ny a aucune notion de schma prtabli et de
validation dune structure. Il nest donc jamais ncessaire dindiquer un attribut pour dire
quil est inconnu ! Il suffit de ne pas dclarer lattribut dans le document. Par exemple,
lorsque vous crez un index secondaire sur des lments du document, cela suppose pour
MongoDB que les valeurs des lments valent NULL si elles ne sont pas trouves dans le
document. Il ny a donc plus besoin de grer ces valeurs lorsquelles nont pas de sens
dans le document. Cette forme de reprsentation des donnes est ainsi beaucoup plus
dense que ne lest celle des SGBDR. Dans les moteurs orients colonne, les mtadonnes
des colonnes ne sont pas prdfinies la cration de la table. En fait, la colonne doit tre
exprime chaque cration dune ligne. Elle peut sy trouver ou non. On est donc dans le
mme cas de figure : il ny a pas rellement de schma explicite, et les colonnes peuvent
tre diffrentes dune ligne lautre. Au lieu de devoir poser un NULL en cas dabsence de
valeur, il suffit de ne pas exprimer la colonne. Pour cette raison, les SGBD orients
colonnes nintgrent pas le concept de NULL, et on les appelle des entrepts de donnes
maigres (le terme anglais sparse est assez difficile traduire dans ce contexte. On
trouve parfois la traduction littrale parse , ce qui ne veut pas dire grand-chose).
Problme rsolu ?
Donc les moteurs NoSQL rsolvent le problme des NULL ? Oui, mais il reste deux choses
signaler. Dabord, les NULL sont-ils un rel problme ? Ils gnent les requtes par leur
logique trois tats. Dans ce cas, problme rsolu. En ce qui concerne loccupation
despace des NULL, il est minime dans les SGBDR, et on ne peut pas vraiment mettre
lconomie despace de stockage au crdit des moteurs NoSQL. Labsence de relation
entre les tables entrane en gnral beaucoup de redondance de donnes et donc, NULL ou
pas NULL, les moteurs NoSQL occupent beaucoup plus despace de stockage quune
SGBDR au modle correctement normalis. Il sagit donc plus dun gain en clart pour la
programmation quen stockage.
Ironiquement, il nous est arriv de voir des NULL dans les donnes des moteurs NoSQL,
notamment en MongoDB. Non pas que MongoDB le demande, mais simplement parce
quil sagissait dun import des donnes dun SGBDR, et que la routine dveloppe pour
cet import ne se proccupait pas de tester si le contenu des colonnes tait ou non NULL pour
gnrer llment dans le document JSON. Le script dimport gnrait des documents qui
comportaient chaque colonne et crivait le mot NULL comme valeur de llment, le cas
chant.

Le transactionnel et la cohrence des donnes


Dans le monde informatique, une transaction est une unit daction qui doit respecter
quatre critres, rsums par lacronyme ACID, et quon nomme donc lacidit de la
transaction. Ces critres sont prsents dans le tableau 2-1.
Tableau 2-1. Critres ACID de la transaction

Critre Dfinition
Une transaction reprsente une unit de travail qui est valide intgralement ou totalement annule.
Atomique
Cest tout ou rien.
La transaction doit maintenir le systme en cohrence par rapport ses rgles fonctionnelles.
Durant lexcution de la transaction, le systme peut tre temporairement incohrent, mais lorsque
Cohrente
la transaction se termine, il doit tre cohrent, soit dans un nouvel tat si la transaction est valide,
soit dans ltat cohrent antrieur si la transaction est annule.
Comme la transaction met temporairement les donnes quelle manipule dans un tat incohrent,
Isole elle isole ces donnes des autres transactions de faon ce quelle ne puisse pas lire des donnes en
cours de modification.
Durable Lorsque la transaction est valide, le nouvel tat est durablement inscrit dans le systme.

Cohrence peut aussi se dire consistance. La notion de cohrence est importante, et cest
lun des lments les plus sensibles entre le monde du relationnel et le monde NoSQL. Les
SGBDR imposent une rgle stricte : dun point de vue transactionnel, les lectures de
donnes se feront toujours (dans les niveaux disolation par dfaut des moteurs) sur des
donnes cohrentes. La base de donnes est visible en permanence sur un tat cohrent.
Les modifications en cours sont donc caches, un peu comme sur la scne dun thtre :
chaque acte dune pice de thtre se droule intgralement sous lil des spectateurs. Si
le dcor doit changer, le rideau se baisse, les spectateurs doivent attendre, les changements
seffectuent derrire le rideau et lorsque le rideau se lve, la scne est de nouveau dans un
tat totalement cohrent. Les spectateurs nont jamais eu accs ltat intermdiaire.
Mais cet tat intermdiaire peut durer longtemps, pour deux raisons : plusieurs instructions
de modifications de donnes peuvent tre regroupes dans une unit transactionnelle, qui
peut donc tre complexe. Ensuite, un SGBDR fonctionnant de faon ensembliste, une
seule instruction de mise jour, qui est naturellement et automatiquement transactionnelle,
peut trs bien dclencher la mise jour de milliers de lignes de table. Cette modification
en masse conservera des verrous dcriture sur les ressources et crira dans le journal de
transaction ligne par ligne. Tout ceci prend bien videmment du temps.

Relchement de la rigueur transactionnelle


Une transaction, cest donc un mcanisme disolation dune opration simple ou
complexe. Elle est importante dans le cadre dun SGBDR, car du fait du modle
relationnel, une donne complexe va se dcomposer dans plusieurs tables et devra donc
faire lobjet de plusieurs oprations dcriture. Si je considre une donne comme une
commande client, qui comporte les informations du client, des produits commands et de
la facture, il faudra excuter plusieurs commandes SQL dinsertion, sur les tables client,
commande et facture. Le langage SQL ne permet de cibler quune table la fois dans la
commande INSERT. Lopration logique de linsertion dune donne complexe devra se
traduire par plusieurs oprations physiques dinsertion, et devra tre regroupe dans une
transaction explicite pour sassurer quil nest pas possible de se retrouver dans la base de
donnes avec des donnes partiellement crites.
On comprend bien quun moteur NoSQL, bas sur le principe de lagrgat, comme nous
en avons discut, ne prsente pas ce genre de problme. Dans MongoDB par exemple, on
crit en une seule fois un document JSON qui agrge toutes les informations de la
commande. : plus besoin par consquent dune transaction explicite. De fait, les critres de
la transaction changent de sens : lcriture est naturellement atomique car le document est
crit en une fois, et elle est naturellement isole car le document est verrouill durant
lcriture. Le besoin dune gestion explicite dune transaction complexe disparat, car
latomicit nest plus le fait du langage, mais dune structuration de la donne dcide par
larchitecte ou le dveloppeur.
Il faut donc repenser le concept des critres transactionnels la lumire dun systme qui
gre diffremment ses donnes, et dont les possibilits et les exigences sont autres.
Les systmes NoSQL agrgent les donnes, mais quand ils sont distribus, ils les
dupliquent. Cela repose le problme transactionnel dans le cadre de la rplication. Si on
crit une donne plusieurs fois, sur plusieurs nuds dun cluster, cette criture redondante
sera-t-elle atomique, cohrente, isole et durable ? Cest dans ce contexte quil faut
comprendre les discussions autour de la cohrence (consistency) des critures dans un
moteur NoSQL. Nous allons tudier cet aspect plus en dtail.

Distribution synchrone ou asynchrone


Nous entrons donc ici brivement dans des problmatiques dinformatique distribue. La
distribution de donnes peut se concevoir de deux faons : synchrone ou asynchrone. Une
distribution synchrone signifie que le processus de rplication des donnes garantit que les
rplicas soient tous aliments avant de considrer que lcriture est termine. Une
distribution asynchrone va autoriser la rplication se faire hors du contrle du processus
de mise jour. Il ny aura donc pas de garantie stricte que la rplication seffectue avec
succs.
Le mode de rplication synchrone va permettre de garantir la cohrence des donnes dans
un systme distribu, tel que nous venons de le voir. Dans ce cadre, la cohrence est
assure par consensus. Le consensus en informatique, cest simplement laccord de
plusieurs processus, locaux ou distants, sur une valeur commune. Cest un concept
essentiel en calcul et en stockage distribu. Dans lidal, tous les processus faisant partie
dun traitement devraient pouvoir participer au consensus, mais il est ncessaire de
prendre en compte les risques de dfaillance, et donc, un bon protocole permettant
datteindre un consensus doit tre tolrant aux dfaillances dun ou de plusieurs nuds,
pour arriver former un quorum (une dcision la majorit) plutt quune dcision
lunanimit.
Assurer une rplication base de consensus en tolrant les pannes nest possible que sur
un rseau synchrone. Cette affirmation a t prouve dans un article de Fischer, Lynch et
Paterson titr Impossibility of distributed consensus with one faulty process 6. Cela
signifie une chose : si vous voulez assurer une cohrence distribue, vous devez travailler
de faon synchrone. Si vous souhaitez favoriser les performances et travailler de faon
asynchrone, vous ne pourrez pas garantir la cohrence de votre rplication. Dans les
systmes asynchrones, on parle donc souvent de cohrence finale (eventual consistency)
pour exprimer le fait que la cohrence nest pas garantie immdiatement mais que des
mcanismes vont permettre dassurer la mise jour des rplicas de faon asynchrone avec
un dlai.

La transaction distribue
Les moteurs relationnels nont pas le choix : ils doivent garantir lacidit de la transaction,
donc la cohrence des critures. Si vous voulez distribuer une base de donnes
relationnelle, vous devez donc tre dans un rseau synchrone et utiliser un protocole
spcifique qui assure de faon distribue la cohrence de cette transaction. Il sagit de ce
quon appelle une transaction distribue.
Comme son nom lindique, une transaction distribue sapplique sur plusieurs machines.
Son implmentation est relativement complexe. Elle sappuie sur la prsence sur chaque
machine dun gestionnaire de ressources (ressource manager, RM) qui supporte en
gnral la spcification X/Open XA rdige par lOpen Group for Distributed Transaction
Processing. Les machines sont supervises par un gestionnaire centralis appel le
Transaction Processing Monitor (TPM). Au moment de la validation (commit) de la
transaction, le TPM organise une validation en deux phases (two-phase commit, 2PC),
reprsente sur la figure suivante.
Figure 2-2
Validation deux phases dans une transaction distribue

Lorsque la transaction est prte tre valide, une premire phase prpare la validation sur
tous les sous-systmes impliqus, jusqu ce que le TPM reoive un READY_TO_COMMIT de la
part de tous les RM. Si cest le cas, la seconde phase de validation relle peut commencer.
Le TPM envoie des ordres de COMMIT aux RM et reoit de leur part des messages de
COMMIT_SUCCESS. La procdure est donc assez lourde et peut tre source de ralentissement
dans les systmes transactionnels qui lutilisent intensment.
Autre remarque : la validation deux phases permet de vrifier quune transaction peut
sexcuter de faon atomique sur plusieurs serveurs. Il sagit en fait dune version
spcialise des protocoles de consensus des systmes distribus. La premire phase de la
validation sert sassurer que les participants sont prts valider, cest une phase de vote.
Si tout le monde est daccord, la seconde phase ralise la validation. On peut se demander
ce qui se passerait si lun des sous-systmes venait crasher aprs la phase de vote, la
seconde phase de validation nayant pas encore t ralise. Dans certains rares cas, cela
peut provoquer une erreur de la transaction. Mais dans la plupart des cas, si la machine en
erreur redmarre et restaure ltat du moteur transactionnel, ce dernier finira par valider la
transaction. Vous voyez peut-tre o se situe galement le problme : 2PC est un protocole
bloquant. La transaction reste ouverte jusqu ce que tous les participants aient envoy le
COMMIT_SUCCESS. Si cela dure longtemps, des verrous vont rester poss sur les ressources
locales et diminuer la concurrence daccs.

Paxos
La transaction distribue est principalement utilise dans le monde des SGBDR pour la
rplication. Elle souffre notamment dun dfaut rdhibitoire qui la rend inutilisable dans le
monde NoSQL : labsence de tolrance aux pannes. Dans la transaction distribue, si un
acteur ne rpond pas, la transaction est annule. Il sagit en fait dune forme de consensus
lunanimit o tous les nuds doivent tre prsents. Lobjectif dun moteur NoSQL est
dassurer une monte en charge sur un nombre thoriquement illimit de nuds, sur du
commodity hardware. tout moment, un nud peut donc tomber en panne. Il faut par
consquent appliquer un protocole de consensus la majorit.
Le pre des protocoles de consensus sappelle Paxos. Paxos est un protocole propos pour
la premire fois en 1989, notamment par Leslie Lamport, le bien connu crateur de
LaTeX. Il existe donc depuis longtemps et a profit dun certain nombre damliorations,
notamment en termes de performances, pour rpondre au mieux aux besoins dans un
environnement distribu moderne. Avec Paxos, vous pouvez maintenir un tat partag et
synchrone entre plusieurs nuds. Pour quun tel protocole fonctionne dans le monde rel,
il est important quil soit tolrant aux pannes. Il est maintenant admis quon ne peut btir
un systme informatique distribu sans une forme de rsistance aux dfaillances
matrielles ou de rseaux. Nous verrons dans ce livre que les moteurs NoSQL distribus
ont tous des mcanismes de tolrance de panne. Cest un lment ncessaire. Paxos inclut
plusieurs mcanismes de tolrance de panne, notamment parce quil se base sur une forme
de consensus la majorit et quil peut donc continuer son travail mme si un ou plusieurs
nuds sont tombs. Si une majorit des nuds est prsente et accepte les modifications,
Paxos pourra rpliquer les donnes.
Il ny a pas dimplmentation officielle de Paxos, il sagit de la description dun protocole
et les implmentations diverses peuvent varier dans les dtails. Une implmentation trs
utilise dans les outils qui tournent autour dHadoop sappelle Zookeeper, un gestionnaire
de consensus et dtat distribu.
Mais dun point de vue gnral, la garantie de la cohrence sur des systmes distribus est
contraignante et entrane des diminutions de performances en criture,
proportionnellement au nombre de nuds, alors que lobjectif de la distribution, en tout
cas dans le contexte de notre rflexion sur NoSQL, est daugmenter les performances par
une monte en charge horizontale. Cest pour cette raison que loption de la cohrence
finale est choisie dans plusieurs moteurs NoSQL. Le fait que certains moteurs NoSQL ne
permettent pas dassurer la cohrence des donnes est lun des sujets majeurs de discorde
entre le monde relationnel et le NoSQL. Cest aussi lun des sujets chauds en raison dun
axiome bien connu dans le monde NoSQL, appel le thorme CAP.

Le thorme CAP
En juillet 2000, lors du symposium sur les principes de linformatique distribue
(Principles of Distributed Computing, PODC) organis par lACM, le professeur Eric
Brewer de luniversit de Californie Berkeley fit une prsentation inaugurale intitule
Towards Robust Distributed System. Eric Brewer est non seulement professeur
luniversit, mais aussi cofondateur et Chief Scientist de la maintenant dfunte socit
Inktomi, que les moins jeunes dentre nous connaissent comme un des moteurs de
recherche web importants de lre pr-Google.
Les transparents de cette prsentation sont disponibles sur le site dEric Brewer :
http://www.cs.berkeley.edu/~brewer/. Il sagit dune rflexion gnrale sur la conception
de systmes distribus, ce qui intresse spcialement dans le monde du NoSQL. Nous
pensons quil est utile de rsumer trs brivement les rflexions dEric Brewer, ce qui
nous fera nous intresser au fameux thorme CAP. Classiquement, la focalisation de
linformatique distribue est ou tait faite sur le calcul et non sur les donnes. Cest pour
des besoins de calcul quon crait des clusters ou des grids de travail, pour atteindre une
puissance de calcul multiplie par le nombre de nuds.
Cluster et grid
On fait en gnral la diffrence entre un cluster et un grid de machines de la faon suivante : un cluster est un
groupe de machines situ dans le mme espace gographique, cest--dire dans le mme data center. Un grid est un
ensemble de machines distribues dans plusieurs data centers.

Lexemple tout public de ceci est le projet SETI@home. Ce dernier utilise les machines
des utilisateurs volontaires travers le monde pour analyser les donnes du projet afin de
dtecter lventuelle prsence dune intelligence extraterrestre
(http://setiathome.ssl.berkeley.edu/).
Mais, comme laffirme Eric Brewer, le calcul distribu est relativement facile. Le
paradigme Hadoop le dmontre : un algorithme MapReduce, qui distribue le travail et
agrge les rsultats, nest pas particulirement difficile concevoir et mettre en uvre.
Ce qui est difficile, cest la distribution des donnes. ce sujet, Brewer nonce le
thorme CAP, une abrviation de trois proprits :
consistency (cohrence) : tous les nuds sont jour sur les donnes au mme moment ;
availability (disponibilit) : la perte dun nud nempche pas le systme de fonctionner
et de servir lintgralit des donnes ;
partition tolerance (rsistance au morcellement) : chaque nud doit pouvoir fonctionner
de manire autonome.
Le cas particulier de la rsistance au morcellement
Lexpression partition tolerance nest pas toujours trs claire. On entend par l quun systme partitionn doit
pouvoir survivre aux difficults du rseau. La dfinition donne par Seth Gilbert et Nancy Lynch est la suivante :
Le rseau peut perdre arbitrairement beaucoup de messages envoys de lun lautre. Il sagit ici dune
proprit du rseau. Cela ne signifie donc pas quun systme soit partitionn, mais cela dcrit sa capacit survivre
aux alas de la perte de partitions ou de communication entre les partitions. Il ne sagit jamais dune garantie totale
daccs partir dun seul nud une situation idale impossible atteindre mais bien dune capacit la survie
et la rsilience aussi pousse que possible.

Les bases de donnes partages ne peuvent satisfaire que deux de ces critres au plus.

Figure 2-3
Le thorme CAP

En 2002, Seth Gilbert et Nancy Lynch du MIT (Massachusetts Institute of Technology) ont
publi un papier visant apporter une dmonstration de ce principe. Gilbert et Lynch
analysent ce trio de contraintes sous langle des applications web et concluent quil nest
pas possible de raliser un systme qui soit la fois ACID et distribu.
Si on regarde les bases de donnes relationnelles traditionnelles selon ce thorme, elles
russissent en matire de cohrence et de support du partitionnement et bien sr de
consistance travers la garantie ACID des transactions, mais pas en matire de
disponibilit.
Cohrence vs disponibilit
Si lobjectif dun systme distribu comme une base NoSQL est dassurer une disponibilit maximale, cela signifie
simplement que toute requte envoye au systme NoSQL doit retourner une rponse (le plus rapidement possible,
mais cela nest pas en soi une exigence). Il faut donc pour cela que la perte dun ou de plusieurs nuds nait pas
dincidence sur les rponses. Dans un systme qui privilgie la consistance, on doit sassurer que les donnes sont
bien lues partir du ou des nuds qui contiennent les donnes les plus fraches, ou que tous les nuds sont jour
avant de pouvoir lire la donne, ce qui pose des problmes de disponibilit de linformation.

Nous aborderons les solutions techniques apportes par les moteurs NoSQL dans le
chapitre suivant. Mais nous pouvons indiquer ici que les solutions des moteurs NoSQL
sont assez varies et plus complexes que ce que vous avez peut-tre dj entendu dire. Il
ne sagit pas, pour les moteurs NoSQL asynchrones, dun abandon pur et simple de la
cohrence pour favoriser la disponibilit, les risques sont trop importants. Tout le monde
nest pas prt tout miser sur un SGBD distribu qui ne prsente aucune garantie de
maintien de cohrence de ses donnes, une sorte de niveau disolation chaos.

PACELC
Le thorme CAP est encore aujourdhui sujet de dbat. Certains en soulignent les
imperfections, dautres laffinent en proposant des modles plus complets, comme le
modle PACELC de Daniel Abadi du dpartement de Computer Science de luniversit
Yale.
Le modle PACELC est une sophistication du thorme CAP qui a lavantage de proposer
un cadre dimplmentation plus souple, avec plus de choix. Il nous a sembl intressant
den dire un mot pour montrer nous le verrons en pratique dans la partie II prsentant les
moteurs NoSQL que la cohrence nest pas forcment un critre quon respecte
scrupuleusement ou quon abandonne. Ce nest pas blanc ou noir. Des moteurs comme
Cassandra permettent de dcider chaque instruction du niveau de cohrence et de
durabilit. Dans un moteur relationnel, le seul critre sur lequel il est possible davoir une
action est lisolation, comme nous lavons vu. Un moteur comme Cassandra offre plus de
souplesse dans la gestion transactionnelle. Nous en reparlerons dans le chapitre 11, ddi
Cassandra.
PACELC est donc un concept de Daniel Abadi. Sa prsentation est disponible ladresse
suivante : http://fr.slideshare.net/abadid/cap-pacelc-and-determinism. Le propos dAbadi
est que le thorme CAP est trop simple, voire simpliste, et quil est principalement utilis
comme excuse pour abandonner rapidement la cohrence. Il est facile daffirmer Le
thorme CAP dit quon ne peut pas partitionner, conserver de bonnes performances et
maintenir la cohrence des donnes, donc je laisse tomber la cohrence des donnes .
Mais, mme si on reste dans loptique du CAP, on peut avoir la disponibilit (A,
Availability) et la cohrence si lon na pas de partition. Un systme peut trs bien tre
partitionn ou non, et donc grer diffremment la cohrence dans ces deux cas. Le modle
PACELC part donc de ce principe et snonce comme une forme darbre de dcisions,
reprsent sur la figure 2-4.
Figure 2-4
Le modle PACELC

Le raisonnement est le suivant : si lon est en prsence dune partition (P), le systme va-t-
il choisir entre la disponibilit (A) ou la cohrence (C) ? Sinon (E pour Else), le systme
va-t-il choisir entre la latence (L) ou la cohrence (C) ?
Un systme comme Dynamo est de type PA/EL : en prsence dune partition, il privilgie
la disponibilit au dtriment de la cohrence, sinon il choisit la latence. En dautres
termes, il na jamais le souci de maintenir la cohrence. De lautre ct du spectre, un
moteur relationnel respectant lACIDit de la transaction sera PC/EC : la cohrence sera
toujours privilgie. On se dit donc quil manque le meilleur des choix, PA/EC, o la
cohrence est privilgie quand son cot est acceptable. Cette option nest pas encore
rellement mise en place dans les moteurs NoSQL. Elle lest dans des moteurs
hybrides comme GenieDB (http://www.geniedb.com/), un moteur de stockage pour
MySQL qui offre une couche de monte en charge horizontale.

Journalisation et durabilit de la transaction


Nous avons vu dans les caractristiques ACID de la transaction que la durabilit de cette
transaction est un lment important. Il est vrai quil est plutt important de ne pas perdre
ses donnes. La durabilit semble a priori quelque chose de naturel : si la modification est
crite quelque part sur le disque, elle est donc durable, en tout cas dans les limites de la
solidit du matriel. Pourquoi donc indiquer dans les caractristiques dune transaction
quelle doit tre durable ? En fait, dans beaucoup de SGBDR, tout comme dans ce quon
appelle les bases de donnes en mmoire dans le monde SQL, les oprations de
modification de donnes seffectue en mmoire vive, dans un cache de donnes souvent
appel le buffer, et qui vite les critures directement sur le disque. Les critures dans des
pages de donnes sont des critures alatoires, qui peuvent se produire nimporte quelle
position dans les fichiers de donnes, et ce type dcriture est trs pnalisant pour les
performances.
Amplification dcritures
Paradoxalement, les effets des critures alatoires sont encore plus nfastes sur les disques SSD, cause dun
phnomne appel lamplification des critures (write amplification). La mmoire flash doit tre efface avant
dtre rcrite. Les donnes sont crites en units nommes pages, mais effaces en plus grandes units, les blocs.
crire des donnes signifie donc : lire un bloc, crire les donnes encore valides de ce bloc, puis les nouvelles
donnes. Ce nest pas trs efficace. Les disques SSD implmentent souvent un ramasse-miettes pour diminuer ce
problme, mais cela implique quand mme du dplacement de donnes. Ensuite, selon les modles de SSD, une
distribution des critures est ralise pour viter que des secteurs soient plus soumis aux critures que les autres et
atteignent prmaturment leur limite de modification (une technique appele wear leveling). Leffacement et
lcriture, ainsi que les dplacements ventuels dus aux mcanismes dcriture de la mmoire flash font que la
mme criture peut tre physiquement multiplie. Les modles de SSD affichent un taux damplification pour
indiquer le nombre de fois o lcriture est multiplie.
Si, pour viter les critures alatoires, on reste en RAM, donc en mmoire volatile, il est
ncessaire de prvoir un mcanisme dcriture sur le disque pour viter de perdre ses
donnes en cas darrt de la machine. Le mcanisme choisi pratiquement dans tous les cas
est le systme du journal. Encore une fois, la traduction franaise est difficile. Le
mcanisme sappelle Write-Ahead Logging (WAL) en anglais, qui pourrait se traduire
littralement par journalisation dcritures anticipes. Sa reprsentation schmatique est
illustre sur la figure 2-5.

Figure 2-5
Write-Ahead Logging

Lcriture est faite au pralable sur un support de stockage, mais sous forme journalise,
dans un fichier qui crit squentiellement les modifications sans se proccuper de leur
allocation finale dans un fichier de donnes. Il sagit alors dune criture squentielle,
beaucoup moins coteuse quune criture alatoire. La donne est galement inscrite dans
un cache en mmoire de faon pouvoir tre directement manipule par le SGBD.
Admettons maintenant que la machine tombe. Lorsquelle redmarre, le journal est relu et
les modifications appliques dans les donnes, comme reprsent sur la figure 2-6.

Figure 2-6
Phase de redmarrage du WAL

Cette relecture du journal au redmarrage de la base prend du temps, et empche les


donnes dtre immdiatement accessibles. Afin de limiter cette problmatique, une
synchronisation du buffer avec les donnes durables est effectue intervalles rguliers,
concentrant donc les effets des critures alatoires sur une priode de temps matrise,
souvent configurable.
La technologie du WAL est la plus efficace et a fait ses preuves. Par consquent, elle est
presque universellement utilise, et les moteurs qui ne limplmentaient pas et donc
nassuraient pas une relle durabilit des critures, lont souvent ajoute au fil des
versions. Cest par exemple le cas avec MongoDB dans sa version 1.8 sortie en mars
2011. Depuis la version 2, la journalisation est active par dfaut.
Certains moteurs comme HBase permettent dcrire directement sur le fichier de donnes
ou de grer le cache dont nous venons de parler. Cette fonctionnalit sappelle le log
flushing, soit le nettoyage du journal en franais. Prenons donc HBase comme exemple
pour illustrer les diffrentes options de gestion du journal, qui sont assez communes aux
moteurs NoSQL.

Lexemple de HBase
HBase peut crire ou non dans le WAL. Une proprit boolenne de la classe
org.apache.hadoop.hbase.client.Mutation dont drivent les classes Append Delete et Put du client
HBase pour Java est nomme writeToWAL. Si writeToWAL est false, les critures seront
inscrites seulement en mmoire (dans lquivalent dun buffer, appel le memstore en
HBase). Cette option est lvidence une optimisation de performance, mais elle est trs
risque. Aucune durabilit nest assure et des pertes de donnes peuvent donc se produire
si la machine (le RegionServer en HBase) tombe.
En HBase, le comportement par dfaut est dcrire dans le journal, puis dcrire
physiquement la donne juste aprs. Le vidage du journal peut aussi tre configur pour
tre diffr. Cest configurable table par table en utilisant les proprits de celles-ci dans la
classe HTableDescriptor, qui contient une valeur DEFERRED_LOG_FLUSH qui peut tre retourne
laide de la proprit isDeferredLogFlush() et modifie par la mthode
setDeferredLogFlush(boolean isDeferredLogFlush). Lintervalle de vidage peut-tre dtermin par
loption suivante du serveur de rgion : hbase.regionserver.optionallogflushinterval. Par dfaut,
elle est de 1 seconde (1 000 millisecondes).

Big Data et dcisionnel


La logique de la croissance de linformatisation et de la globalisation dInternet aboutit
une augmentation formidable des volumes de donnes stocker et manipuler. Cette
augmentation de volume est de plus imprvisible. Une entreprise fournissant des services
ou des biens des clients rgionaux par les canaux de ventes traditionnels que sont par
exemple la prospection ou les catalogues papier, peut estimer la croissance de son volume
de ventes, et mme un succs inespr restera dans un volume grable. En revanche, une
entreprise fonctionnant sur Internet, qui ne dlivre pas de bien manufactur mais un
service qui reste propre lenvironnement du rseau, peut connatre une croissance
foudroyante et exponentielle de sa frquentation. Elle doit tre prte soutenir une trs
forte augmentation de charge en un rien de temps. Pour cela, une seule solution est
envisageable : une monte en charge horizontale, cest--dire que la charge sera distribue
sur des serveurs disposables (commodity servers), ajouts une architecture qui permet le
plus simplement possible et de faon transparente de multiplier les nuds.
Lexemple de Zynga
Zynga est une socit californienne qui a beaucoup de succs. Elle produit des jeux sur Facebook comme CityVille
et FarmVille, qui comptent des dizaines de millions dutilisateurs. Lorsque Zynga a lanc FarmVille sur Facebook
en juin 2009, la socit estimait que si elle obtenait 200 000 utilisateurs en deux mois, son jeu serait un succs.
Mais ds son lancement, le nombre dutilisateurs augmenta dun million par semaine, et ce pendant vingt-six
semaines daffile.
Il est intressant de noter que cette extraordinaire croissance a t possible mme avec un moteur de bases de
donnes relationnelles en stockage disque. Larchitecture de Zynga, hberge en cloud sur Amazon EC2, a pu
passer de quelques dizaines de serveurs plusieurs milliers. Le stockage est assur dans une base MySQL, mais les
donnes sont principalement caches en mmoire par memcached, un systme de mmoire cache distribu, et cest
l o nous retrouvons du NoSQL.

Dans le monde du Big Data, nous pouvons faire la mme distinction que dans le monde
des SGBDR concernant lutilisation des donnes. Elle a t thorise en 1993 par Edgar
Frank Codd, entre un modle OLTP et un modle OLAP.

OLTP et OLAP
Ces modles reprsentent des cas dutilisation des bases de donnes. OLTP dcrit une
utilisation vivante et oprationnelle des donnes. Ces dernires sont en constante
volution, des ajouts, des modifications et des suppressions interviennent tout moment,
et les lectures sont hautement slectives et retournent des jeux de rsultats limits. Les
bases de donnes constituent le socle des oprations quotidiennes des entreprises. Si on
transpose le besoin dans le monde NoSQL, on peut dire que les traitements OLTP
ncessitent une latence plus faible, donc de meilleurs temps de rponse, avec
potentiellement un volume de donnes plus rduit. OLAP, ou traitement analytique en
ligne, dcrit une utilisation analytique, dcisionnelle des donnes. Il sagit de volumes
importants de donnes historiques qui reprsentent toutes les donnes de lentreprise, et
qui sont requtes afin dobtenir des informations agrges et statistiques de lactivit de
lentreprise (dcisionnel, ou Business Intelligence), ou pour extraire des informations
nouvelles de ces donnes existantes laide dalgorithmes de traitement des donnes
(Data Mining). Dans le monde NoSQL, cette utilisation correspond des besoins de
manipulation de grands volumes de donnes, sans avoir ncessairement besoin de pouvoir
les travailler en temps rel. En dautres termes, une certaine latence est acceptable.
Ces deux modes dutilisation des donnes ont des exigences et des dfis diffrents. Un
systme de gestion de bases de donnes relationnelles est bien adapt une utilisation
OLTP. Lorsquune base relationnelle est bien modlise, elle permet une grande efficacit
des mises jour grce labsence de duplication des donnes, et une grande efficacit
dans les lectures grce la diminution de la surface des donnes. Jusqu un volume
mme respectable, un bon SGBDR offre dexcellentes performances, si lindexation est
bien faite.

Les exigences de lOLAP


En revanche, le modle relationnel nest pas adapt une utilisation OLAP des donnes
car dans ce cas de figure, toutes les oprations sont massives : critures en masse par un
outil dETL (Extract, Transfer, Load), les lectures galement massives pour obtenir des
rsultats agrgs.
Tableau 2-2. Les diffrences entre OLAP et OLTP

OLTP OLAP
Mises jour au fil de leau Insertions massives
Recherches slectives Agrgation de valeurs sur de grands ensembles de donnes
Types de donnes divers Principalement donnes chiffres et dates
Utilisation partage entre mises jour et Utilisation en lecture seule la plupart du temps
lectures
Besoins de calculs sur des donnes volumineuses, souvent sans
Besoins temps rel
exigence dimmdiatet

Les limitations dOLAP


Le modle OLAP est lanctre du Big Data. Il a t conu dans un contexte o le hardware
restait cher et o les volumes taient raisonnables. Il tait logique de concentrer ses
fonctionnalits sur une seule machine, ou un groupe limit de machines, et de construire
un systme intgr qui soccupe du stockage et de linterrogation des donnes travers un
modle organis en cubes.
Cette conception a pourtant un certain nombre de dfauts quand on la ramne aux besoins
daujourdhui. Premirement, elle suppose une modlisation des donnes prliminaire. Il
faut btir un modle en toile, donc structurer ses donnes sous forme de table de fait et de
table de dimensions. Crer un modle pralable implique quon va structurer les donnes
par rapport des besoins prdfinis. Si de nouveaux besoins mergent aprs la cration du
systme, peut-tre que la structure cre ne permettra pas dy rpondre.
Cette structuration suppose en plus quon doive utiliser des outils dimportation et de
transformation des donnes (des outils dETL) pour prparer la donne lanalyse. Cela
implique galement quon ne garde pas forcment tout lhistorique des dimensions par
exemple, et quil faudra au besoin des stratgies de gestion des dimensions changeantes
(slowly changing dimensions).
Comme on tablit des relations entre une table de fait et des tables de dimensions, des
liens subsistent entre les tables, ce qui rend leur distribution plus difficile. De plus, ce
modle fait et dimensions sapplique une analyse multidimensionnelle des donnes, mais
pas forcment une recherche de type data mining ou machine learning. On est contraint
certains types de processus.

OLAP vs Big Data


Pour rpondre ces limitations, ce quon appelle le Big Data prsente une conception
diffrente de lanalytique. Une fois de plus, la donne nest pas trs structure, en tout cas
il ny a pas dans un systme Big Data de schma explicite de la donne. Lobjectif est de
stocker lintgralit des donnes, sans choix, sans transformation, sans remodlisation. On
stocke la donne brute, parce quon ne sait pas lavance ce quon va vouloir en faire,
quelles sont les informations quon va vouloir en tirer. Cest fondamentalement le
paradigme Hadoop qui nous a permis de penser de cette manire. Si on y rflchit,
Hadoop est un systme qui permet de distribuer des fonctions de traitement sur un cluster
de machines qui hbergent galement des donnes.
Dans ce chapitre, nous explorons quelques diffrences entre le monde SQL et le monde
NoSQL. Nous avons parl de schma explicite et du langage dclaratif quest SQL. Pour
que ce systme fonctionne, il faut prdfinir une structure qui soit adapte aux requtes
travers ce langage normalis quest SQL, qui travaille sur des ensembles de donnes
structures de faon prcise. Inversement, un langage de programmation de moins haut
niveau comme Java offre des usages beaucoup plus gnraux, qui ne supposent pas une
structuration prdfinie de la matire avec laquelle il va travailler. Au lieu de dfinir une
requte avec un langage de haut niveau adapt une certaine structure de donnes,
Hadoop est un framework o lon dveloppe des fonctions en Java (ou dans un autre
langage du mme type) qui vont donc sadapter la structure des donnes disposition, et
qui permettent denvoyer ces fonctions directement plus proches de ces donnes pour
effectuer un traitement. On envoie simplement des fonctions sur un cluster de machines.
Sur Hadoop, il est donc inutile de structurer la donne. On peut trs bien se contenter de
fichiers plats, de type CSV par exemple, ou de tout type de structure de base de donnes
ou de srialisation comme JSON ou Thrift. Il suffit de stocker au fil de leau les donnes
telles quelles arrivent, dans toute leur richesse, et ensuite de les traiter au besoin laide
de fonctions, et donc de rpondre toutes les demandes futures quelles quelles soient.

La conception de Nathan Marz


Lun des acteurs influents du Big Data sappelle Nathan Marz. Travaillant dans une
entreprise rachete par Twitter en 2011, il a cr une unit au sein de Twitter charge de
dvelopper un environnement de traitement distribu, avant de quitter lentreprise en 2013
pour fonder sa propre socit. Cest le crateur dApache Storm, lune des principales
applications de traitement distribu en temps rel. Nous en reparlerons.
Il a men une rflexion sur le Big Data qui a dbouch sur un livre en fin de rdaction
chez lditeur Manning (http://manning.com/marz/) et sur un concept darchitecture quil a
appel larchitecture Lambda. Nous y reviendrons galement. Nous nous contenterons ici
de parler des principes lis au stockage des donnes. Un environnement Big Data suivant
larchitecture Lambda accueille des donnes immutables, selon un mode dajout
uniquement (append-only). Cest lun des fondements du systme : la donne est ajoute
dans toute sa richesse, et elle est conserve tout jamais. Dans ce cas, la conception de la
donne ressemble celle dun journal (un log). Cest le seul moyen de pouvoir tracer un
historique complet des donnes. Labsence de possibilit de mise jour garantit galement
quil y a aucun risque de perte de donnes. Tous ceux qui ont dj utilis un moteur de
base de donnes relationnelle ont vcu ces deux expriences : un jour, ils ont regrett de
ne pas avoir structur une table avec un historique et davoir perdu cette dimension au
moment o on leur demandait des informations de ce type ; un autre jour, ils ont perdu des
donnes cause dune mauvaise manipulation ou dun bogue dans le programme client.
Le principe de larchitecture Lambda est de ne plus jamais toucher aux donnes aprs leur
insertion. Les outils de traitements batch de type Hadoop vont permettre de traiter ces
grands volumes de donnes pour produire des rsultats sous forme de vues matrialises et
donc de restructurer une copie de ces donnes brutes pour rpondre aux besoins.
Admettons quil y ait un bogue dans le programme de traitement qui gnre ces vues
matrialises. Mme si on dtecte le bogue six mois aprs la mise en production, on sera
capable de corriger le problme en supprimant les vues matrialises, en corrigeant le
bogue, et en relanant le traitement batch.
La structure des donnes nest pas vraiment importante. Comme on envoie des fonctions
pour traiter les donnes, elle peut sadapter tous types de format, du fichier plat au
moteur de base de donnes. Donc on spare vraiment ici le concept de moteur de
traitement du concept de stockage. Il vaut mieux dailleurs stocker les donnes dans le
format le plus universel possible, par exemple du JSON ou du CSV, de faon tre
capable de le lire partir de nimporte quel langage et dans un futur mme lointain, un
moment o un ventuel format propritaire aurait t dprci. La structure propre
lanalyse par les outils de lecture et dinterrogation sera implmente dans les vues
matrialises, qui peuvent donc tre facilement recres.

Dcisionnel et NoSQL
Les environnements de traitement distribu de types batch, ou maintenant temps rel, vont
peut-tre remplacer terme les outils OLAP du march. En tout cas, on assiste pour
linstant une convergence des deux approches, surtout grce la popularit de
lapproche Big Data. Les diteurs de solutions dcisionnelles ont tous intgr Hadoop ou
un algorithme MapReduce distribu. Nous avons parl de Microsoft qui supporte
maintenant Hadoop avec une plate-forme nomme HDInsight, mais la distribution NoSQL
dOracle peut galement tre utilise avec Hadoop, avec un peu de bricolage (voir
http://www.oracle.com/technetwork/articles/bigdata/nosql-hadoop-1654158.html). Un
autre exemple est Vertica, un diteur de solutions dcisionnelles qui a t lun des
premiers dvelopper un connecteur Hadoop (http://www.vertica.com/the-analytics-
platform/native-bi-etl-and-hadoop-mapreduce-integration/). Citons galement Pentaho, la
solution dcisionnelle libre (http://www.pentahobigdata.com/ecosystem/platforms/hadoop)
qui sintgre totalement avec Hadoop, offrant un environnement graphique de cration de
travaux distribus. Dautres socits se spcialisent dans la mise disposition
denvironnements dcisionnels bass sur Hadoop, telles que Datameer
(http://www.datameer.com/), ou dveloppent des interfaces pour Hadoop destines au
dcisionnel. Lanalytique est donc un des cas dutilisation majeur de MapReduce.

3. Pramod J. Sadalage et Martin Fowler, NoSQL Distilled: A Brief Guide to the Emerging World of Polyglot Persistence,
Addison Wesley, 2012.
4. Eric Evans, Domain-Driven Design: Tackling Complexity in the Heart of Software, Addison Wesley, 2003.
5. Le terme shard est souvent utilis dans les moteurs NoSQL pour exprimer un partitionnement gr automatiquement
par le systme. Nous en parlerons au chapitre 3.
6. Journal of the ACM, vol. 32, n 2, avril 1985
3
Les choix techniques du NoSQL

Dans les deux chapitres prcdents, nous avons prsent le mouvement NoSQL sur un
plan historique et par opposition au modle relationnel. Ces analyses sont intressantes,
mais on peut aussi adopter un troisime point de vue, essentiellement technique. Car si les
conceptions ou les idologies qui gravitent autour des technologies permettent de mieux
les comprendre, ce qui compte en dfinitive, ce sont les technologies elles-mmes.
Ici, nous allons donc dtailler les caractristiques techniques du NoSQL. On peut les
regrouper en deux grandes tendances, qui correspondent des besoins et des utilisations
spcifiques. Certains moteurs sont ainsi principalement utiliss pour rpondre des
problmatiques dinterrogation de donnes trs volumineuses (Big Data), dautres pour
assurer le traitement le plus rapide possible des donnes moins volumineuses mais
requrant un flux optimis, ce qui relve du domaine des bases de donnes en mmoire.
Nous exposerons dans ce chapitre les choix techniques communs, ainsi que les spcificits
des implmentations tendant vers une utilisation Big Data ou vers la performance. Sachez
en tout cas que si vous choisissez une solution NoSQL pour vos besoins, vous vous
orienterez vers des outils trs diffrents selon que vous tes dans un cas dutilisation ou
dans lautre.

Linterface avec le code client


Nous lavons vu, le langage SQL impose une faon de penser dclarative, ensembliste et
parfois fonctionnelle qui nest pas forcment naturelle pour les dveloppeurs ayant t
forms aux langages impratifs. Les problmatiques de dfaut dimpdance obligent en
plus les dveloppeurs travailler travers des chanes de caractres, ce qui nest pas trs
pratique. Les ORM rglent ce problme mais montrent leurs limites lorsquon veut
optimiser les performances de laccs aux donnes. Le mouvement NoSQL est n pour
plusieurs raisons, mais un des gains du point de vue du dveloppement est une meilleure
intgration du code serveur dans le code client. Cest une qualit des bases NoSQL : elles
sadaptent au dveloppeur et ses contraintes, au lieu de lui en inventer dautres. Elles
offrent souvent, par exemple, des structures de donnes proches de celles qui sont dj
utilises par les dveloppeurs pour lchange de donnes ou la srialisation des objets,
comme le JSON. Les pilotes sont implments comme bibliothques des langages de
dveloppement les plus utiliss, et il est trs facile dappeler les fonctions des bases
NoSQL travers des bibliothques dobjets intgres dans ces langages. Les exemples les
plus flagrants de cette facilit sont les entrepts de paires cl-valeur en mmoire, comme
Redis, qui permettent de manipuler des structures qui sont semblables aux structures de
donnes natives des programmes clients (tableaux, tables de hachage). Prenons un
exemple trs simple de ceci avec Redis. Le code suivant est trs court :
#!/usr/bin/python

import redis
r = redis.StrictRedis(host=localhost, port=6379, db=2)

r.hmset(contact:ajar, dict(
prenom=Emile,

nom=Ajar,

Profession=Ecrivain

)
)

dic = r.hgetall(contact:ajar)

print dic

Aprs avoir ouvert une connexion au serveur Redis et choisi la base de donnes 2 (en
Redis, les bases de donnes sont indiques simplement par leur numro), nous utilisons la
mthode hmset du client Python, qui correspond la commande HMSET de Redis. Redis est un
moteur de paires cl-valeur en mmoire qui offre plusieurs structures de donnes comme
des strings, des sets (ensembles), des tables de hachage, etc. HMSET permet de stocker une
table de hachage en tant que valeur de la paire. Ici, notre cl est la chane contact:ajar.
Nous stockons directement dans cette cl un dictionnaire Python, quivalent dune table
de hachage. Le pilote Redis pour Python soccupera de faire la traduction pour nous.
Ensuite, nous rcuprons notre donne laide de la mthode hgetall, qui extrait une table
de hachage stocke dans Redis partir de la cl fournie en paramtre. Grce au support
des types de donnes de Python, cette mthode retourne directement un dictionnaire. La
dernire commande, le print de ce dictionnaire, donne le rsultat suivant :
{nom: Ajar, Profession: Ecrivain, prenom: Emile}

Les fonctionnalits serveur


Alors que dans le monde relationnel, lutilisation de curseurs ou dautres types de
mthodes procdurales pour manipuler les donnes de la base est dans la grande majorit
des cas une approche viter, et qui pose de grands problmes de performances, les bases
NoSQL ont pris la direction inverse. Il ny a en gnral aucune complexit dlgue vers
le serveur. Le serveur NoSQL retourne un document (une paire cl-valeur) ou une
collection de documents, et ces derniers seront ensuite ouverts et parss par le code client.
Les moteurs NoSQL sont souvent utiliss comme de simples entrepts de donnes. Le
comportement au niveau du serveur na pas la richesse du modle relationnel, o il est
possible de crer des contraintes, des dclencheurs, des fonctions, des procdures
stockes, bref tout un comportement qui peut parfois les transformer en une couche
applicative (un middle-tier) part entire. Cest en tout cas ltat des lieux lheure
actuelle. Certainement, au fur et mesure que les moteurs NoSQL vont voluer, les
comportements ct serveur vont senrichir. Le paradigme classique pour offrir des
fonctionnalits de traitement niveau du serveur, cest encore une fois MapReduce. Dans
CouchDB et Couchbase Server, on peut crer des vues dans des documents de design, qui
consiste en deux vues JavaScript (un autre langage peut tre choisi) : une vue map qui
traite chaque document de la base de donnes, et une vue reduce facultative qui offre des
possibilits dagrgation. Lintrt de ce mcanisme est de matrialiser la vue sous forme
dindex B-Tree, ce qui offre dexcellentes performances ensuite en interrogation.
Il sagit donc toujours deffectuer ce type de traitement : gnrer des vues pour interroger
les donnes est souvent calculer des agrgats. Riak offre galement un mcanisme de
MapReduce intgr o des fonctions peuvent tre crites en JavaScript ou en Erlang.
Comme Riak est un systme distribu dcentralis o nimporte quel nud peut agir en
tant que moteur de requte, une demande MapReduce consiste envoyer les fonctions
map et reduce lun des nuds, qui devient le coordinateur du traitement. Riak tant un
moteur cl-valeur, laccs aux donnes se fait principalement par la cl, ce qui est assez
pauvre pour des besoins traditionnels de requtage. Vous pouvez maintenant crer des
index secondaires pour effectuer des recherches si la partie valeur est compose de
documents JSON et, pour tout autre type de traitement, vous pouvez donc envoyer des
fonctions MapReduce. La diffrence avec une requte traditionnelle de SGBDR, cest que
nous ne sommes plus ici dans un comportement de requte en temps rel, mais plus dans
une opration de traitements batch avec un temps de traitement qui peut tre relativement
long selon le volume des donnes et la complexit du traitement. Il sagit en quelque sorte
de lajout dune fonctionnalit analytique un moteur oprationnel.
Nous serons amens le rpter dans ce livre : avant dutiliser rellement en production
une technologie, renseignez-vous sur la faon dont elle est implmente dans un moteur
particulier. Riak est un systme oprationnel dont lobjectif principal est doffrir de bons
temps de traitement sur des donnes volumineuses avec un dimensionnement lastique.
Ses fonctionnalits MapReduce ne doivent pas tre considres comme un outil de
premier plan, mais plus comme une possibilit utiliser en dernier ressort pour couvrir un
besoin ponctuel. Le traitement MapReduce en Riak est lent et coteux pour le cluster,
principalement en JavaScript. De plus, vous navez pas une garantie absolue de traiter
toutes les donnes, dans le sens o lalgorithme de MapReduce ne prend pas en compte la
rplication. Les donnes vont tre cherches une fois sur un nud du cluster qui est
suppos les avoir, mais si ce nud ne comporte pas les donnes ou la dernire version des
donnes, MapReduce nira pas chercher ces donnes ailleurs. Autre chose prendre en
considration : Riak ne supprime pas physiquement directement ces donnes mais place
des marqueurs de suppression appels tombstones, pendant trois secondes par dfaut. Le
traitement MapReduce va soprer galement sur ces tombstones, et cest vous de les
filtrer dans le code de votre traitement MapReduce en vrifiant une information dans les
mtadonnes des objets rcuprs. Soyez donc toujours attentif aux contraintes
dimplmentation.
Prenons un dernier exemple, celui de MongoDB. Cest un moteur qui a une richesse de
requtage assez rare dans le monde NoSQL, et vous permet dexprimer des critres de
filtrage complexe. Pour un traitement ct serveur, vous pouvez excuter du code
JavaScript en utilisant une fonction nomme eval(), ce qui savre pratique pour des petites
oprations effectuer sur des collections.
Ainsi, vous pouvez dfinir une fonction JavaScript, lexcuter avec un appel db.eval() et
rcuprer ce rsultat dans votre code client. Voici un exemple simple, tir de la
documentation de MongoDB, qui nest en soi pas trs utile car il fait double emploi avec
une fonction dagrgation dj existante, le count() : elle retourne simplement le nombre de
documents dans une collection.
db.eval( function(){return db[collection].find({},{_id:ObjId()}).length();} );

Pour calculer des agrgats, vous pouvez soit utiliser une fonctionnalit MapReduce, soit
un framework plus rcent nomm Aggregation Framework. Le traitement MapReduce sur
MongoDB nest pas particulirement rapide, et les gens qui avaient adopt MongoDB
pour sa richesse fonctionnelle souffraient ensuite de limpossibilit dextraire des donnes
agrges dans un temps de rponse raisonnable. Linterprteur MapReduce est JavaScript,
dabord SpiderMonkey, puis partir de la version 2.4, V8, le moteur JavaScript beaucoup
plus rapide de Google. Cela amliore un peu les choses en termes de temps de traitement,
mais on peut vraiment mieux faire. MongoDB a donc dvelopp lAggregation
Framework en C++ et la intgr dans le moteur de requte de MongoDB. Nous en
verrons un exemple dans le chapitre 8 ddi MongoDB.

Les protocoles daccs aux donnes


Les moteurs NoSQL implmentent diffrentes mthodes daccs aux donnes. Vous avez
dj compris que, quels que soient ces protocoles, des bibliothques existent pour tous les
grands langages clients afin de les rendre plus faciles dutilisation. Voyons toutefois les
interfaces les plus communes entre le client et le serveur.

Interfaces natives
Des serveurs comme MongoDB utilisent un protocole natif pour communiquer avec le
serveur. Il sagit dune communication en mode question-rponse, base sur un socket
ouvert avec le serveur, sur le port TCP 27017 par dfaut. Des messages sont envoys,
composs dun en-tte et dun corps de message comprenant des structures assez simples.
Par exemple, la structure dun message dinsertion (qui est identifi par un opcode dans
len-tte qui indique quelle est lopration demande) est la suivante :
struct {

MsgHeader header; // en-tte de message contenant lopcode et dautres informations


int32 ZERO; // 0 - rserv pour une utilisation future

cstring fullCollectionName; // le nom de la collection implique

BSON[] documents; // un ou plusieurs documents insrer dans la collection


}

Les documents envoys sont en format BSON, qui est simplement un JSON binaris
un peu plus compact (voir le chapitre 4 sur les structures de donnes).
Il serait donc facile de dvelopper un pilote pour MongoDB. Cela nest pas vraiment
ncessaire car MongoDB Inc., la socit qui dveloppe MongoDB, sest appliqu
raliser des pilotes (drivers) pour la quasi-totalit des langages clients importants, du C++
Erlang, et liste dans sa documentation les pilotes dvelopps par la communaut
(http://wiki.mongodb.org/display/DOCS/Drivers). Ainsi, dvelopper en MongoDB
consiste utiliser des mthodes dun objet collection pour insrer, supprimer, requter les
documents, et ainsi de suite. Quelques exemples de ces appels figurent dans le chapitre 8
de cet ouvrage.
Protocol Buffers
Certains moteurs utilisent un protocole cr et largement utilis en interne par Google,
nomm Protocol Buffers, ou protobuf. Il sagit dune dfinition de format dchange de
donnes standard qui peut servir tout type de donne structure. Contrairement
MapReduce, protobuf est librement accessible et tlchargeable ladresse suivante :
http://code.google.com/p/protobuf/. Les moteurs qui implmentent protobuf sont Riak
(http://docs.basho.com/riak/1.2.0/references/apis/protocol-buffers/) et HBase (mais pour
ses communications internes, interservices uniquement, voir cet article de blog pour les
dtails techniques : http://blog.zahoor.in/2012/08/protocol-buffers-in-hbase/).
Lutilisation de protobuf est simple : vous dfinissez une structure de message dans un
fichier .proto, puis vous utilisez le code fourni par Google pour gnrer du code de
manipulation du message. Le code fourni par Google ne supporte que trois langages : C+,
Java et Python. Pour dautres langages, vous devrez chercher des implmentations
ralises par la communaut, ou faire le travail vous-mme en vous inspirant des sources
du code de Google. Utilisons notre exemple dentre de blog.
Normalement, nous devrions tlcharger et compiler le compilateur protobuf disponible
ladresse Google mentionne prcdemment. Sur Ubuntu, nous navons pas besoin de le
faire, protobuf est disponible sous forme de paquet, probablement parce que protobuf est
utilis par Canonical pour la fonctionnalit Ubuntu One, son service de stockage sur le
cloud. Nous installons donc les paquets ncessaires :
sudo apt-get install protobuf-compiler python-protobuf

Puis nous crons un fichier .proto contenant la dfinition de notre structure de donnes :
package passerelles;
message Article {

required int32 id = 1;
required string titre = 2;
message Auteur {

required string prenom = 1;

required string nom = 2;


required string email = 3;

repeated Auteur auteur = 3;


}

message Articles {

repeated Article article = 1;


}

Ce document illustre quelques-unes des possibilits de protobuf. La structure est


hirarchique : un message peut contenir dautres messages, et ces messages peuvent tre
indiqus comme tant prsents plusieurs fois dans le message contenant, avec le mot-cl
repeated. Chaque message est compos de types de donnes scalaires simples (la liste des
types supports est disponible ladresse suivante :
https://developers.google.com/protocol-buffers/docs/proto ?hl=fr#scalar) ou dautres
messages. Chaque lment peut tre dclar comme obligatoire (required) ou optionnel
(optional), et une valeur par dfaut peut tre spcifie pour les lments optionnels, qui sera
utilise lorsque le code parse un message protobuf o llment nest pas prsent.
Finalement, dans la dfinition du message, un numro indiquant la squence des lments
est obligatoire.
numrations
Nous ne les avons pas utilises dans notre exemple, mais protobuf supporte galement des numrations (des listes
de valeurs) comme type de donne pour des lments du message. Ces numrations se dfinissent directement
dans le message, en tant que structure enum.

Ce fichier crit et cr, il nous reste gnrer le code de gestion de cette structure. Pour ce
faire, nous utilisons le compilateur protobuf protoc, que nous appelons ici dans le rpertoire
o nous avons sauvegard notre fichier :
protoc -I=./ --python_out=./ ./passerelles.proto

Le compilateur prend un rpertoire source (I pour input), un type de destination (nous


indiquons python_out pour gnrer du code Python dans le rpertoire courant) et un fichier
.proto dentre. Le rsultat est un fichier Python nomm <nom du package>_pb2.py, ici
passerelles_pb2.py. Le fichier Python gnr contient des descripteurs de format et dfinit
des classes pour crer des messages. Nous en reproduisons ici la signature uniquement :

Les classes dfinies ici utilisent le concept de mtaclasse en Python, qui permet dinjecter
par rflexion des fonctionnalits une classe existante. Ceci sort un peu du cadre de ce
livre, considrez simplement que le code ncessaire la gestion du message est inject
dans la classe que vous voyez ici. Utilisons le module gnr dans un code dexemple
Python :
#! /usr/bin/python

# -*- coding: utf-8 -*-


import passerelles_pb2

article = passerelles_pb2.Article()

article.id = 1
article.titre = unicode(pourquoi les lphants ont-ils de grandes oreilles ?,

utf-8)

auteur = article.auteur.add()
auteur.prenom = Annie

auteur.nom = Brizard

auteur.email = annie.brizard@cocomail.com
f = open(exemple.msg, wb)

f.write(article.SerializeToString())
f.close()

Ici, nous importons le module passerelles_pb2 gnr par protoc et nous crons une instance
de notre article, que nous alimentons avec des donnes. Nous convertissons le titre en utf-
8 pour que les caractres accentus soient correctement encods par protobuf. Finalement,
nous utilisons la mthode SerializeToString() pour crire le rsultat dans un fichier. Le
fichier exemple.msg contient une chane compacte du contenu du message avec seulement
quelques caractres de contrle pour sparer les lments.
Cet exemple montre quel point protobuf est simple utiliser. On peut sen servir pour
changer des informations en RPC entre un client et un serveur, comme cest le cas dans
son utilisation avec Riak. Une implmentation en RPC pour protobuf utilisant des sockets
est disponible en Python cette adresse : http://code.google.com/p/protobuf-socket-rpc/.
Le fait quun message protobuf srialis soit assez compact pourrait aussi inciter
lutiliser comme format de stockage. Ce nest pas un choix fait par les grands moteurs
NoSQL, mais certains lont jug intressant, notamment les dveloppeurs de Twitter qui
lutilisent pour stocker des milliards de tweets. Une prsentation sur le sujet est disponible
ladresse suivante : http://fr.slideshare.net/kevinweil/protocol-buffers-and-hadoop-at-
twitter.

Thrift
Thrift est un autre protocole, en ralit un framework initialement dvelopp et utilis en
interne par Facebook, et donn en 2007 la fondation Apache. Il est utilis comme
interface, soit directement, soit de bas niveau, par certains moteurs NoSQL. Tout comme
protobuf, il permet de dfinir une structure de message. On y ajoute une interface de
service qui permet de dfinir les oprations supportes sur cette structure, et un
compilateur gnre limplmentation dans le langage souhait. Thrift est encore un peu
plus que cela : il incorpore tous les niveaux ncessaires la cration de services. Les
diffrents niveaux de Thrift sont illustrs sur la figure 3-1.

Figure 3-1
La pile Thrift

Une couche serveur permet de dfinir diffrents types de serveurs, quils soient single-
thread ou multi-thread. La couche processeur est le code gnr par Thrift pour effectuer
les traitements des messages dfinis. La couche protocole permet dempaqueter les
donnes dans des formats comme JSON, compact, dense, binaire, etc. Enfin, la couche
transport met disposition le code pour changer les donnes, par exemple en fichiers
disque ou via sockets, HTTP, etc. Il sagit donc dune bibliothque complte de
dveloppement de services.
Thrift supporte nativement beaucoup plus de langages que protobuf, en voici une liste non
exhaustive : C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk et
Ocaml.
Voyons comment fonctionne Thrift en dveloppant un petit exemple. Contrairement
protobuf, Thrift nest pas disponible sous forme de paquets binaires pour Ubuntu. Nous
devons donc le tlcharger et le compiler. Installons au pralable les paquets ncessaires
la compilation :
sudo apt-get install libboost-dev libboost-test-dev libboost-program-options-dev
libevent-dev automake libtool flex bison pkg-config g++ libssl-dev

Ensuite, tlchargeons la version actuelle de Thrift, disponible sur son site


http://thrift.apache.org/download/, et compilons-la :
wget https://dist.apache.org/repos/dist/release/thrift/0.9.0/thrift-0.9.0.tar.gz
tar xvzf thrift-0.9.0.tar.gz

cd xvzf thrift-0.9.0
./configure

Lappel de configure va tester la prsence de langages sur notre systme. Ici, ce qui nous
intresse est lutilisation avec Python. Celui-ci tant prsent sur notre systme, la
configuration affiche, entre autres, cette information :
Python Library:
Using Python .. : /usr/bin/python

Si vous voulez utiliser Thrift avec un langage, veillez donc ce quil soit pralablement
install, et soyez attentif la prsence de cette information vers la fin de loutput de
configure. De mme, si vous tes sur Ubuntu, la compilation de Thrift pour votre langage
ncessite linstallation de certains paquets, lists sur cette page daide :
http://thrift.apache.org/docs/install/ubuntu/. De notre ct, afin dviter dinstaller les
dpendances ncessaires pour le langage Ruby qui tait install sur notre systme, nous
avons utilis loption --without-ruby de configure :
./configure without-ruby

La liste des options de configure est disponible avec :


./configure --help

Ensuite, nous compilons, excutons les tests et installons Thrift avec make :
make
make check

sudo make install

Nous testons si Thrift est correctement install :


thrift -version

ce qui retourne :
Thrift version 0.9.0
Nous installons alors le module Python pour utiliser Thrift :
sudo pip install thrift

Tout comme pour protobuf, nous crons un fichier de dfinition de donnes. Essayons ici
de le crer au plus proche de ce que nous avons fait pour protobuf.
namespace py passerelles
struct Auteur {

1:required string prenom,

2:required string nom,


3:required string email

struct Article {
1:required i32 id,

2:required string titre,


3:required Auteur auteur

}
service Articles {
void ping();

bool addArticle(1:Article article);


Article getArticle(1:i32 id);
}

Nous dclarons dabord un espace de nom optionnel. Thrift nous permet de crer des
espaces de noms diffrents pour chaque langage, cest la raison pour laquelle nous
indiquons ici py pour notre compilation pour Python. Nous crons ensuite une structure
pour lauteur, et une structure pour larticle. Le fonctionnement est assez semblable
protobuf, les lments sont numrots en tte au lieu de ltre la fin, et le mot-cl struct
est utilis pour dfinir une structure. Des enum peuvent aussi tre utiliss et une struct peut
tre employe dans une autre. Finalement, nous dfinissons un service, qui est une
interface comprenant la signature des mthodes que nous voulons voir cres dans le code
gnr. Nous sauvegardons cette dfinition dans un fichier que nous nommons
article.thrift, puis nous gnrons le code Python avec le compilateur Thrift :

thrift -r --gen py article.thrift

Loption --gen py nous permet dindiquer que la cible est du code Python. Le rsultat est
gnr dans ./gen-py/passerelles, selon lespace de nom que nous avons dfini. Le code
gnr est un peu plus complexe que pour protobuf, mais basiquement, nous nous
retrouvons avec un fichier Articles.py qui contient la dfinition du service, et un script
nomm Articles-remote qui permet dutiliser en ligne de commande les fonctionnalits de
transport de Thrift.
Thrift tait le protocole bas niveau de communication avec Cassandra jusqu sa version 2
sortie en 2014. Cassandra dfinissait une interface sous forme de fichier Thrift qui donnait
toutes les structures et fonctions pour communiquer avec le serveur. Cette interface est
toujours disponible et sappelle le mode daccs par lAPI. partir de la version 2, laccs
API est dprci et le protocole officiel sappelle CQL, pour Cassandra Query Language.
Il sagit dune implmentation dun langage dclaratif trs proche du SQL. On pourrait
donc considrer que Cassandra nest plus un moteur NoSQL. Nous reparlerons galement
de cette dcision de la communaut de dveloppement de Cassandra de changer
radicalement de mode daccs. Cela a en tout cas amlior les choses en termes de
rapidit, parce que laccs CQL est natif et binaire, et les benchmarks ont montr de nets
gains de performance.
Dautres moteurs utilisent Thrift, notamment HBase
(http://wiki.apache.org/hadoop/Hbase/ThriftApi). Il reprsente une bonne solution pour
accder HBase partir de clients non Java, car loffre de pilotes natifs pour des
langages autres que Java nest pas encore trs tendue en ce qui concerne HBase. Par
ailleurs, loutil ElasticSearch
(http://www.elasticsearch.org/guide/reference/modules/thrift.html), proche du monde
NoSQL, prsente une interface Thrift.
Thrift est galement linterface pour Apache Storm, le framework de traitement de flux en
temps rel distribu la popularit croissante. Thrift est utilis par Storm pour la
communication des donnes entre ses composants sur un cluster, et lAPI de bas niveau
Nimbus, la machine matre de Storm, est en Thrift.
HiveServer et HiveServer2 sont des services optionnels intgrs Apache Hive, une
infrastructure trs utilise, base sur Hadoop, pour permettre des clients dutiliser les
fonctionnalits de requtage de Hive ; ils utilisent tous deux une interface Thrift. Cest
galement le cas du serveur JDBC dApache Spark, un successeur trs intressant et
beaucoup plus complet de Hive, qui offre un framework complet de traitement distribu.

Apache Avro
Il existe galement un autre systme de srialisation de la fondation Apache, nomm Avro
(http://avro.apache.org/). Il est plus rcent et offre une certaine souplesse par rapport
protobuf et Thrift, surtout parce quil nest pas ncessaire de le compiler au pralable
comme cest le cas pour les deux protocoles prcdents. Le schma est dfini en JSON
avec la donne, ce qui permet de traiter les structures en Avro dynamiquement. De plus,
les champs nont pas besoin dtre numrots comme dans protobuf et Thrift. Une
tentative a t faite de dvelopper une interface Avro pour Cassandra, qui devait
thoriquement remplacer Thrift, mais principalement par manque de popularit, ce projet
na pas t suivi. Avro est peut-tre une solution davenir, elle commence bien sintgrer
dans lcosystme Hadoop (voir http://blog.cloudera.com/blog/2011/07/avro-data-
interop/) et fait partie des dveloppements grs par Doug Cutting (il en a crit les
spcifications, voir http://avro.apache.org/credits.html). Cest donc un dveloppement
surveiller. Deux modules existent pour Python : le premier, nomm simplement Avro, est
relativement lent, cest la raison pour laquelle un second module compil en C est aussi
disponible, fastavro (http://pypi.python.org/pypi/fastavro/).

REST
Pour linstant, nous avons explor des protocoles plutt classiques, de type RPC (Remote
Procedure Call), qui lient un client et un serveur avec des interfaces bien dfinies et
assurent en gnral le maintien dune connexion TCP. Une autre vision de la
communication entre machines est possible, sous la forme darchitecture oriente services
ou darchitecture oriente ressources, dans le cas de REST. REST (Representational State
Transfer) est une architecture spcifique lappel de ressources disponibles dans un
environnement htrogne et distribu le Web, en un mot. Elle a t dfinie par Roy
Fielding, lun des principaux auteurs de la spcification HTTP et un contributeur au
dveloppement du serveur HTTP Apache.
REST se base sur le protocole de base du Web, le HTTP. Lide est simple et cest ce qui
la rend intressante. Le protocole HTTP est bas sur lchange de documents et il
comporte des verbes, ou mthodes, qui permettent dindiquer un type daction voulue un
serveur HTTP, en gnral un serveur web. Pourquoi ne pas simplement utiliser ces verbes
pour communiquer avec des ressources et des services distants ? Tous les langages de
programmation ont dj des bibliothques qui permettent de communiquer de cette
manire. De plus, une demande REST est sans tat, toute la demande est contenue dans
son appel, et tout le rsultat est renvoy en rsultat. Il est inutile, la base, de maintenir
une connexion. Cest simple et lgant. Cela permet aussi aux serveurs de simplifier leurs
interfaces avec le client : nul besoin de maintenir une connexion ouverte, de conserver une
vue cohrente des donnes durant la vie de cette connexion, etc. Plusieurs moteurs NoSQL
ou apparents (nous pensons ici ElasticSearch) implmentent une interface REST. Le
plus vident est CouchDB, mais des moteurs comme :
Riak http://docs.basho.com/riak/latest/references/apis/http/
HBase http://wiki.apache.org/hadoop/Hbase/Stargate
Neo4J http://docs.neo4j.org/chunked/milestone/rest-api.html
offrent galement des interfaces REST.
Un fournisseur de ressources qui respecte les rgles du modle REST est dit RESTful. Ces
rgles sont assez simples : sparation des responsabilits entre client et serveur, aucun
maintien dtat entre des demandes, dcouplage du client et du serveur par utilisation
dinterfaces, etc. Les verbes HTTP senrichissent au fil des versions des RFC (Request
For Comments, documents qui dfinissent les aspects techniques dInternet) et ne sont pas
forcment tous supports par la majorit des serveurs HTTP. Une interface REST pourrait
au besoin en utiliser toute la richesse, mais en pratique, toutes les oprations ncessaires
peuvent tre ralises laide de six mthodes.
Tableau 3-1. Les mthodes REST

Mthode Utilisation
GET Mthode utilise pour rcuprer une reprsentation dune ressource, cest--dire tout type de donne.

HEAD
Comme GET, mthode qui permet denvoyer une demande mais elle ne retourne pas le rsultat,
seulement len-tte. Utile pour rcuprer des mtadonnes.
Mthode permettant de crer une ressource, de stocker une reprsentation dune ressource.
PUT
Elle permet donc linsertion et la mise jour. La rgle veut quun envoi ultrieur de la mme ressource
(portant le mme identifiant) remplace lancienne ressource. Dans certains moteurs comme CouchDB,
ceci est ralis par la mthode PUT en crant une nouvelle version du document.
Mthode qui offre peu prs les mmes fonctionnalits que PUT, mais dune faon plus souple.
POST
On considre que POST envoie une requte au serveur, alors que PUT envoie une ressource stocker, cette
dernire tant indique dans lURL (voir plus loin). POST peut aussi tre utilise pour transmettre une
demande daction au fournisseur de la ressource, sans quil y ait stockage de donnes.
DELETE Mthode qui permet simplement de supprimer une ressource.
OPTIONS Mthode qui retourne les ressources disponibles sur un serveur.
Lutilisation de ces mthodes sera illustre un peu plus loin.
Dans le monde du Web, la mthode GET est la plus rpandue. Par exemple, pour accder au
site des ditions Eyrolles, un navigateur web envoie une requte HTTP dont les deux
premires lignes pourraient tre :
GET / HTTP/1.1
HOST: www.editions-eyrolles.com

Le verbe GET demande un document, il indique le chemin souhait, ici la racine (/).
Ensuite, len-tte de la requte est constitu dune liste de paires cl-valeur. Nous avons
seulement montr la premire, lindication du serveur qui envoyer la demande.
Exemple avec une ressource REST : parse.com

Pour illustrer lutilisation de ressources REST laide dun langage client, nous allons
utiliser un service en ligne qui propose une interface REST. Il en existe beaucoup
dsormais, le plus vident est Amazon S3 (Simple Storage Service) qui offre un systme
de stockage dans le cloud. Nous avons trouv un service intressant qui nous permettra de
dmontrer simplement un change de donnes avec REST : le service parse.com
(https://www.parse.com/). Parse est une socit californienne qui propose un systme de
gestion de donnes en ligne destination des dveloppeurs dapplications mobiles. Elle
prend en charge la partie serveur de ces applications. Des API sont disponibles pour IOS,
Android, Windows 8 et une API REST est galement disponible. Nous allons utiliser
loutil curl et du code Python pour communiquer avec le site parse.com. La documentation
de lAPI REST de parse.com est disponible ladresse suivante :
https://www.parse.com/docs/rest.
curl

La faon la plus simple de tester un service REST est dutiliser loutil en ligne de
commande curl. Pour rappel, curl (Client URL Request Library, soit bibliothque de
requtes aux URL des clients en franais, http://curl.haxx.se/) est un outil courant du
monde Unix qui permet dinteragir avec des URL, en utilisant peu prs tous les
protocoles dInternet, et avec une richesse fonctionnelle qui en fait un vrai couteau suisse
du transfert de donnes sur le Web. Curl nest pas toujours install par dfaut sur les
distributions. Vous pouvez lobtenir sur Debian ou Ubuntu en installant le paquet curl :
sudo apt-get install curl

Curl est install par dfaut sur Mac OS X et disponible en binaires pour Windows
ladresse suivante : http://curl.haxx.se/download.html, qui liste les ports de curl sur tous
les systmes possibles et imaginables.
Lavantage de curl
Lutilisation de curl permet dtudier trs simplement le fonctionnement naturel dune ressource REST, sans aucune
couche dabstraction amene par une bibliothque. En utilisant loption -v, nous pouvons en plus voir avec curl
tous les dtails de lenvoi et de la rception des donnes, notamment les en-ttes HTTP, ce qui est trs pratique pour
dboguer. Pour afficher plus de dtails lorsque vous excutez une commande curl comme celles que nous allons
voir, remplacez loption -X par -vX.

Nous avons ouvert un compte sur parse.com et nous avons cr une application nomme
Eyrolles. Nous utilisons le plan basique, gratuit, qui offre un giga-octet de stockage et un
million de requtes et de push de donnes par mois. Sur notre tableau de bord
(https://www.parse.com/apps), nous pouvons visualiser les applications disponibles et
lutilisation du service, comme illustr sur la figure 3-2.

Figure 3-2
Application sur parse.com

Chaque application dispose dun identifiant propre (Application ID) et dune cl client
(Client Key) qui permet lauthentification partir du code client.
Une application parse.com stocke les donnes dans un document compos des paires cl-
valeur avec des types de donnes compatibles JSON (voir le chapitre suivant consacr aux
schmas de donnes dans les bases NoSQL). Ce document est appel un PFObject et il est
contenu dans une classe, ce qui lui confre plus ou moins une fonctionnalit de collection
de documents. Tous les appels lAPI REST se font sur le domaine https://api.parse.com.
Un exemple dURL serait : https://api.parse.com/1/classes/Passerelles/CAQr2WT1r0, qui
correspond donc ladresse dune ressource, en loccurrence le document portant
lObjectId CAQr2WT1r0, dans la classe Passerelles. Ladresse https://api.parse.com/1/ indique
que nous accdons travers la version 1 de lAPI REST. La mthode POST nous permet
dajouter un document. Utilisons donc curl pour ajouter notre article de blog :
Ici, nous indiquons curl que nous effectuons un POST sur la ressource
https://api.parse.com/1/classes/Passerelles. Nous navons pas cr la classe Passerelles
lavance, elle sera automatiquement cre au premier POST dun PFObject dans cette classe.
Les paramtres -H permettent denvoyer des paires cl-valeur den-tte HTTP. Ici, nous
devons fournir lidentifiant de lapplication ainsi que la cl client, et indiquer que le
Content-Type est du JSON, indispensable pour communiquer avec lAPI parse.com. Ensuite,
nous envoyons le document laide du paramtre -d (data). Nous avons d simplifier
notre document, parse.com naccepte pas les documents JSON complexes, et nous oblige
crer des cls sans accents et signes non alphanumriques.
parse.com nous rpond avec un JSON de rsultat, indiquant la date de cration et
lObjectId gnr :

Nous pouvons donc maintenant retrouver notre donne laide dun GET :

qui nous retourne le JSON du document :

Nous pouvons dailleurs aussi le constater dans lexplorateur de donnes du tableau de


bord de parse.com (https://www.parse.com/apps/eyrolles/collections), qui nous offre une
vision tabulaire du document JSON (figure 3-3).

Figure 3-3
Vision du document JSON sur parse.com

Pour modifier un objet, nous utilisons la mthode PUT :

Le document doit contenir les cls modifier, le reste du document ne sera pas touch.
Nous recevons une notification de mise jour :
{updatedAt:2012-11-01T13:57:14.749Z}

Enfin, nous pouvons supprimer lobjet grce la mthode DELETE :

Lobjet est alors silencieusement supprim.


Avantages et inconvnients de linterface REST

REST est un paradigme daccs aux ressources trs lgant et extrmement simple
mettre en uvre. Tous les langages de dveloppement comportent des bibliothques qui
permettent dutiliser le protocole HTTP. En proposant une interface REST, les
fournisseurs de ressources et certains moteurs NoSQL offrent une solution facile daccs
aux donnes. Alors, pourquoi ne pas se simplifier la vie et utiliser une interface REST
pour tous vos appels vers les moteurs de bases de donnes NoSQL qui le supportent ?
Malheureusement, parce que HTTP et REST ne sont pas des protocoles conus pour la
rapidit. Si on prend lexemple de CouchDB, qui offre uniquement une interface daccs
en REST, cest un moteur riche fonctionnellement mais trop lent pour offrir une solution
intressante pour des applications qui ont besoin de manipuler des volumes honorables de
donnes avec une faible latence. Ce nest pas d uniquement REST et une initiative
comme Couchbase (http://www.couchbase.com/), dirige aussi par Damien Katz, le
crateur de CouchDB, propose un dveloppement autour de CouhDB qui rsout un certain
nombre de problmes, en offrant, par exemple, un sharding automatique et une intgration
de memcached. Techniquement, Couchbase est une combinaison de CouchDB et de
Membase, un entrept de paires cl-valeur bas sur memcached. Laccs aux donnes dans
Couchbase est effectu via le protocole binaire de memcached, qui offre de bien
meilleures performances que REST et HTTP.
En conclusion, selon vos besoins, linterfaage en REST avec un dpt de donnes
NoSQL peut savrer tre une bonne solution technique, par sa simplicit et son
universalit. Cependant, elle montrera vite ses limites si vous avez besoin de bonnes
performances.

Lintrt des protocoles pour la persistance


Les frameworks comme Thrift ou Protobuf incluent le support de toutes les couches
ncessaires la manipulation et lchange dinformation structure ou semi-structure.
Mme si vous navez pas besoin dchanger des informations entre services, vous pouvez
a minima en tirer parti pour leur capacit exprimer et persister des structures de
donnes. Pour un projet Big Data par exemple, nous avons dj voqu la sparation entre
donnes et traitement, et les critres particuliers de la donne : immutable, complte,
brute, traite ensuite en batch pour gnrer des vues matrialises. Vous pouvez ainsi trs
bien utiliser Thrift pour structurer la donne que vous allez manipuler dans un tel systme.
Cela vous permet davoir une donne structure qui reste universellement accessible
partir de nimporte quel langage, et dont le format est prenne.
Ajoutons une chose : que vous utilisiez du CSV, du Thrift, de lAvro, peu importe, cest
une bonne ide aussi de compresser les donnes, par exemple avec un algorithme de type
Lempel-Ziv ou driv. Vous allez pouvoir stocker beaucoup plus de donnes sur les
mmes nuds, et vous allez amliorer les performances dentres-sorties, en chargeant
certes un peu plus les processeurs, mais en gnral le compromis est bnfique pour les
performances. Comme vous allez lancer des oprations en batch, vous ntes de toute
faon pas trs sensible ces performances.
Prenons lexemple dHadoop MapReduce. Historiquement, la structure de donnes de
base utilise par les fonctions mapper et reducer est un objet Writable qui reprsente des
paires cl-valeur. Writable implmente un protocole de srialisation simple. Cette
implmentation date du dveloppement original de Doug Cutting pour faire fonctionner
Hadoop pour Nutch (voir notre petit historique dans le chapitre 1). partir de la version
0.17 qui date de 2008, vous pouvez utiliser nimporte quel protocole de srialisation.
Auparavant, la dclaration dune fonction mapper tait la suivante :
class MyMapper implements Mapper {
public void map(WritableComparable key, Writable val,
OutputCollector out, Reporter reporter) throws IOException {

//
}

//
}

alors quelle utilise maintenant (Hadoop 2.6.0) des gnriques dfinis au niveau de la
classe Mapper :
Class Mapper<KEYIN,VALUEIN,KEYOUT,VALUEOUT> extends Object

Et la dfinition de la mthode attend bien sr les types dfinis la cration de lobjet :


protected void map(KEYIN key, VALUEIN value, org.apache.hadoop.mapreduce.Mapper.
Context context) throws IOException, InterruptedException

Les types gnriques


Les types gnriques prsents dans des langages comme Java ou C# permettent de crer des classes manipulant des
donnes dont le type nest pas connu lavance. Lorsque vous crez une instance de la classe, vous indiquez quel
est le type que cette instance va manipuler. Le typage de la classe sera donc effectu la compilation, puisque le
compilateur sait partir de la dclaration dinstanciation de quel type il sagit. Vous pouvez ainsi crer des classes
rutilisables qui restent type-safe.

Donc vous pouvez utiliser nimporte quelle structure dans un travail MapReduce. De plus,
tout le travail pnible a dj t fait par Twitter dans sa bibliothque libre elephant-bird
(https://github.com/twitter/elephant-bird) qui offre des objets InputFormat, OutputFormat et
Writable pour Hadoop en Thrift ou Protobuf avec le support de la compression LZO. Cest
une bibliothque trs utilise par Twitter en interne pour leurs besoins.
Vous trouvez des exemples complets de MapReduce avec Lzo, Thrift et Protobuf dans les
sources delephant-bird cette adresse : https://github.com/twitter/elephant-
bird/tree/master/examples/src/main/java/com/twitter/elephantbird/examples.

Larchitecture distribue
Comme nous lavons vu, lune des raisons qui ont conduit la naissance du NoSQL est de
pouvoir distribuer les donnes sur plusieurs machines, afin dassurer la gestion de donnes
de plus en plus volumineuses, ainsi quune une monte en charge la plus rapide et indolore
possible. Larchitecture distribue est donc au cur du NoSQL. Il existe deux grandes
faons de considrer la distribution des traitements et des donnes : avec ou sans matre.
Les moteurs NoSQL utiliss pour grer de grands volumes de donnes ont fait lun ou
lautre choix, nous allons voir lesquels et comment ils fonctionnent.

La distribution avec matre


La premire solution de la distribution ou du partitionnement de donnes sappuie sur la
prsence dune machine matre, qui conserve la configuration du systme, reoit les
requtes des clients et les redirige vers les machines qui contiennent les donnes dsires.

La rplication matre-esclave
La rplication nest pas de la distribution, cest une copie des donnes qui sert avant tout
assurer la redondance, donc la protection contre la perte de donnes. Cest une technologie
courante dans le monde relationnel, et peu prs tous les moteurs relationnels importants
permettent de mettre en place une rplication matre-esclave. Elle est importante pour
rpondre lexigence de cohrence transactionnelle forte, qui rend difficile les critures
sur plusieurs serveurs, moins de mettre en place un systme de rsolution de conflits. On
crit donc sur le matre, qui se charge de rpliquer les donnes sur les esclaves. Ces
machines secondaires peuvent, en revanche, tre utilises en lecture, tout dpend du
besoin de cohrence de la lecture. En effet, permettre la lecture sur un rplica implique
quil est possible de lire une donne obsolte, qui viendrait dtre mise jour sur le
serveur matre, mais pas encore rplique. Dans le monde NoSQL, ce risque dpend du
caractre synchrone ou asynchrone de la mise jour, comme nous lavons vu.
Exemple de MongoDB

En ce qui concerne la rplication purement matre-esclave, elle est utilise dans


MongoDB, o elle est traditionnellement allie au sharding pour partitionner les donnes
et assurer la redondance. Afin de sassurer de la durabilit de la modification, on peut
indiquer une option lenvoi de la modification au serveur MongoDB, ce que MongoDB
Inc. appelle un write concern, ou en franais prvenance dcriture. Par dfaut, une
opration dcriture sur MongoDB est asynchrone : le code client continue son excution
sans aucune garantie du succs de lcriture sur le serveur.
La mthode pour dfinir le write concern a chang depuis ldition prcdente de ce livre.
Traditionnellement, on pilote ce comportement laide de la commande getLastError, qui
dtermine une option de scurit dcriture. Les options disponibles sont mentionnes
dans le tableau 3-2.
Tableau 3-2. Write concern en MongoDB

Option Description
vide MongoDB a reu la modification en mmoire.
J
(journal) La donne est crite dans le journal (WAL, Write-Ahead Log).

W
En cas densemble de rplicas, cette option dfinit le nombre de rplicas o la donne doit avoir t crite
pour considrer lcriture russie.
Loption w prend comme paramtre un nombre de rplicas sur lesquels lcriture doit avoir
russi, par dfaut 1. Vous pouvez aussi indiquer la valeur majority pour indiquer que
lcriture doit avoir russi sur une majorit de rplicas.
Voici un exemple de commande JavaScript ( saisir, par exemple, dans linvite de
commandes de MongoDB, voir le chapitre 8 ddi MongoDB pour plus de prcisions)
pour activer cette option dans les anciennes versions de MongoDB :
db.runCommand( { getLastError: 1, w: majority } )

Cette option est dfinie par session, et est en gnral intgre dans le pilote du langage que
vous utilisez. Par exemple, le paramtre safe du pilote Python activait getLastError :
collection.save({name: MongoDB}, safe=True)

Elle peut galement tre modifie dans la configuration de lensemble de rplicas pour
affecter le comportement par dfaut de toutes les critures (effectues sans indication
explicite de getLastError), laide de lobjet de configuration rs.conf() de lobjet rs (Replica
Set, ensemble de rplicas).
Le code suivant permet de modifier la configuration par dfaut, excuter dans linvite
JavaScript de MongoDB :
cfg = rs.conf()

cfg.settings = {}
cfg.settings.getLastErrorDefaults = {w: majority, j: true}
rs.reconfig(cfg)

partir de MongoDB 2.6, une mise jour importante sortie en avril 2014, le write
concern est plus logiquement intgr dans le nouveau protocole dcriture, qui ajoute les
commandes insert, update et delete. Ces nouvelles commandes, intgres dans les pilotes
pour les langages clients, comportent un paramtre o le write concern peut tre
mentionn explicitement. La valeur par dfaut reste dfinie par getLastError. Voici pour
exemple la syntaxe de la commande insert :
{

insert: <collection>,

documents: [ <document>, <document>, <document>, ],


ordered: <boolean>,

writeConcern: { <write concern> }

Voici un exemple de valeurs pour le paramtre :


writeConcern: { w: majority, wtimeout: 5000 }

ce qui signifie, un write concern la majorit, avec un dlai dattente de 5 secondes (5000
millisecondes). Loption wtimeout peut tre spcifie globalement avec getLastError et existe
donc dans ce contexte aussi dans les versions antrieures.
Ces nouvelles commandes permettent galement de recevoir un document writeConcernError
qui contient le code et le message dune ventuelle erreur de write concern, comme le
dpassement du dlai dattente.
Lecture sur un esclave
Vous pouvez aussi configurer MongoDB pour lire sur le matre ou sur un esclave, en
spcifiant une prfrence de lecture. Le tableau 3-3 liste les prfrences de lecture
supportes par les pilotes MongoDB depuis la version 2.2.
Tableau 3-3. Prfrence de lecture en MongoDB

Prfrence de
Description
lecture
primary Lecture sur le matre. Une erreur est gnre si le matre est indisponible.

primaryPreferred
Lecture sur le matre. Si le matre est indisponible, par exemple si un basculement est en
cours, la lecture se fera sur un secondaire.
secondary Lecture sur un secondaire. Une erreur est gnre si aucun secondaire nest disponible.
secondaryPreferred Lecture sur un secondaire. Sil ny a pas de secondaire, la lecture se fera sur le matre.

nearest
Lecture sur le membre le plus proche, selon les dductions du client. Le client identifie le
membre le plus proche laide dun ping rgulier sur les membres.

Voici un exemple de connexion avec PyMongo, le pilote Python de MongoDB.


# -*- coding: utf-8 -*-
import sys
from pymongo import MongoReplicaSetClient

from pymongo.errors import ConnectionFailure


from pymongo.read_preferences import ReadPreference
def main():

try:
cn = MongoReplicaSetClient (
localhost:15000,

replicaSet=ReplicaSet1,
read_preference=ReadPreference.SECONDARY,
tag_sets=[{dc: paris}, {dc: lille}]

)
print connexion russie

cn.read_preference = ReadPreference.SECONDARY_PREFERRED
except ConnectionFailure, e:

sys.stderr.write(Erreur de connexion MongoDB: %s % e)

sys.exit(1)
if __name__ == __main__:

main()

Ici, aprs avoir import de PyMongo les modules MongoReplicaSetClient et ReadPreference, nous
ouvrons une connexion MongoDB laide de la classe MongoReplicaSetClient, qui nous
envoyons le nom de lensemble de rplicas (ici, nous avons nomm notre ensemble
ReplicaSet1) et nous indiquons la valeur de read_preference. Nous utilisons aussi la capacit
dindiquer des tags pour choisir quel serveur privilgier dans le jeu de rplicas. Nous
tudierons cette fonctionnalit dans le chapitre 8 ddi MongoDB. Plus loin dans le
code, nous modifions read_preference pour lui attribuer la valeur ReadPreference.SECONDARY. Vous
pouvez donc agir ensuite sur read_preference pour modifier ltat de la connexion.
Attention Pymongo
Selon votre version de MongoDB et de Pymongo, le code prcdent peut changer, et ce, pour deux raisons. Depuis
la version 2.6 de MongoDB a t cr un nouvel objet de connexion qui est utiliser dans vos nouveaux
dveloppements : mongoClient au lieu de connection. De son ct, Pymongo sest mis jour avec deux objets :
MongoClient et MongoReplicaSetClient. Ensuite, partir de la version 3 de Pymongo, qui doit sortir en 2015,
lobjet MongoReplicaSetClient va disparatre pour tre fusionn avec MongoClient. La prsence de deux objets
distincts rsulte dune mauvaise dcision de la part des dveloppeurs du pilote, comme ils lexpliquent dans cette
entre de blog : http://emptysqua.re/blog/good-idea-at-the-time-pymongo-mongoreplicasetclient/.

Le sharding
Le nom anglais shard signifie clat (comme un clat de verre) ou tesson (de
bouteille ou de poterie). Le terme driv sharding dcrit donc lclatement des donnes en
partitions distribues sur plusieurs machines, de faon aussi automatique que possible par
le moteur NoSQL. Ce terme est utilis dans beaucoup de moteurs, et est parfois disponible
par des additions aux moteurs qui ne le supportent pas nativement. Par exemple, au moins
trois extensions sont disponibles pour effectuer du sharding sur CouchDB : BigCouch,
Lounge et Pillow. Par ailleurs, Couchbase Server, bas sur CouchDB, permet le sharding.
Le sharding consiste donc en un partitionnement des donnes, ou clustering ( ce niveau,
les concepts ont tendance se chevaucher). Le terme spcifique de sharding est n pour
dsigner une forme de partitionnement prsentant des caractristiques particulires.
Lclatement est gr automatiquement par le systme. Il ny a, a priori et autant que
possible, aucun besoin de le grer manuellement.
Lclatement est par nature distribu. Cela na pas de sens de crer plusieurs shards sur la
mme machine, en tout cas pas en production.
La rpartition de charge est possible.
Implmentations relationnelles
Le concept de sharding nest pas limit aux bases NoSQL. Il sagit en dfinitive dun partitionnement de donnes
effectu sur une cl, ce qui ne pose pas de problme majeur pour un SGBDR. Par exemple, SQL Azure Federations
est une implmentation du concept de sharding sous SQL Azure, la base de donnes relationnelle de Microsoft sur
son cloud. Dans SQL Azure Federations, chaque base de donnes rside sur un serveur et contient une plage de
cls. Les bases sont fdres ensemble et reprsentent lintgralit des donnes. Le modle est le suivant :
Federation Root Member Atomic Unit (AU) Table. LAtomic Unit correspond un shard.

En soi, le sharding peut aussi tre class dans la section suivante, ddie la distribution
sans matre. MongoDB est un exemple de moteur qui implmente le sharding bas sur une
machine principale qui sait comment sont distribu les shards, et oriente le client. Nous
verrons au chapitre 8 comment mettre en place concrtement le sharding sur MongoDB.

La distribution sans matre


La problmatique dun systme distribu avec matre est bien entendu la prsence dun
SPOF (Single Point Of Failure), cest--dire dun lment non redondant qui reprsente
un risque de dfaillance pour tout le systme. Les moteurs NoSQL qui sinspirent du
modle BigTable de Google sont btis autour dun systme avec matre. Dautres moteurs
comme Redis ou CouchDB ne sont pas nativement distribus, la question ne se pose donc
pas. Des extensions permettent toutefois de les faire voluer vers la distribution des
donnes. Quant aux moteurs inspirs de Dynamo dAmazon, ils se basent sur une
architecture sans matre, o thoriquement toute machine a la mme importance et les
mmes capacits dans le cluster. Lobjectif est de pouvoir assurer un service complet en se
connectant nimporte quelle machine, mme si plusieurs membres du cluster tombent.
Pour btir un systme distribu et dcentralis fonctionnel, il faut rpondre plusieurs
questions : comment diriger les requtes des clients sur les machines qui contiennent
linformation souhaite ? Et comment maintenir ltat du systme, notamment comment
savoir quelles sont les machines qui composent le cluster ? Il faut aussi savoir o et
comment distribuer les donnes, de faon ce quelles soient rparties autant que possible
et quelle puissent tre rpliques sur diffrents sites. Dans la section suivante, nous allons
aborder quelques concepts et technologies qui rpondent ces questions.

La table de hachage distribue


La distribution des donnes implmente par Dynamo et dcrite dans le document dont
nous avons parl est base sur le modle de la table de hachage distribu (DHT,
Distributed Hash Table). Le principe de la DHT est utilis dans les outils dchange de
fichiers comme Gnutella ou BitTorrent. Prenons lexemple de BitTorrent. la base, ce
protocole nest pas tout fait dcentralis. Certes, lchange de fichiers sopre selon un
mode P2P (peer-to-peer), mais la dtection de pairs qui dtiennent le fichier passe par un
serveur, nomm tracker. Tout tlchargement de fichier par BitTorrent doit, dans le
protocole dorigine en tout cas, passer au pralable par la communication avec un tracker,
donc un serveur matre. Pour contourner cette problmatique, le client BitTorrent officiel
implmente une DHT, dont le format est maintenant reconnu par la plupart des clients
BitTorrent. Cette DHT maintient sur chaque client BitTorrent une partie de linformation
dattribution des fichiers, rserve normalement au tracker. En interrogeant dautres
clients, un client BitTorrent peut retrouver des pairs.
Une DHT est reprsente conceptuellement par un espace de cls (keyspace), qui
correspond une grande table de hachage. Cet espace de cls est distribu sur les nuds
du systme. Dynamo, Cassandra, Riak, etc. sont des formes de tables de hachage
distribues, qui maintiennent leurs donnes dans une table scalable de paires cl-valeur
rparties sur un nombre potentiellement infini de nuds. La connaissance de la topologie
du cluster est galement distribue sur chaque noeud du cluster : on peut donc parler dun
systme de stockage en P2P.

Le protocole de bavardage
Un protocole de bavardage (gossip protocol) est une mthode de distribution des
informations virales base sur ce quon pourrait appeler la thorie des pidmies
(thorise par Norman Bailey dans son livre The Mathematical Theory of Infectious
Diseases, 2nd Edition, Hafner Press/MacMillian Pub. Co., 1975). En rsum, si une
personne est contagieuse, elle va entrer en contact avec des sujets rceptifs qui vont
tomber malades et eux-mmes contaminer dautres sujets, ce qui a un effet de croissance
exponentielle. Les systmes distribus peuvent utiliser le protocole de bavardage pour
dissminer des informations, comme la disponibilit ou lajout dun nud dans le systme
ou la modification dune donne.
Dans un protocole de bavardage, les nuds engagent priodiquement une conversation
avec un nombre choisi de machines (des pairs) pour changer des informations (dun
trois nuds toutes les secondes en Cassandra, par exemple). Aprs un certain temps, une
information connue dun seul nud au dpart sera communique tous les nuds.
Comme lchange dinformations ne se fait pas en temps rel, mais selon une forme de
planification relche , le rseau nest pas submerg par les communications entre les
nuds, ce qui le maintient en bonne sant. Cela implique que la distribution totale de
linformation va prendre du temps. Il ne sagit donc pas dune solution valable si on
souhaite que linformation soit disponible pour tous le plus rapidement possible. La figure
3-4 montre de faon schmatique le fonctionnement dun protocole de bavardage.

Figure 3-4
Protocole de bavardage

Ici, le nud A a une information communiquer au systme. Il va entrer en contact avec


un nud choisi au hasard parmi les nuds dont il a connaissance. Cest la communication
numro 1 avec le nud B. Cette communication stablit dans les deux sens : si le nud B
a aussi une information communiquer, il lenverra A durant leur conversation. Ensuite,
intervalles rguliers, chaque nud en contactera un autre. A contacte G et B contact E.
Ensuite, A contacte C, B contacte D et E contacte G. Il se trouve que G a dj reu
linformation de la part de A, ce sont les risques du bavardage : si je colporte une rumeur,
je vais aussi la raconter des gens qui la connaissent dj.
Dans le document dcrivant Dynamo
(http://www.allthingsdistributed.com/2007/10/amazons_dynamo.html), Amazon indique
que le protocole de bavardage lui sert propager les changements de nuds du cluster et
maintenir une vision consistance finale de cette appartenance. Si un nouveau nud est
ajout, il commence publier sa prsence par bavardage et aprs quelque temps, tous les
nuds en seront avertis par change dun historique des changements de membres du
cluster. Le bavardage sert aussi, dans Dynamo, lchange des informations de partitions,
cest--dire la distribution des cls entre les machines (consistent hash space, voir section
suivante), ce qui fait que chaque nud sait quelle est la range de cls gre par tous les
autres nuds du cluster. Cela permet donc chaque machine de recevoir des demandes de
lecture ou dcriture de la part dun client, et de transmettre cette demande un nud qui
gre les bonnes donnes. Riak, un moteur NoSQL dcentralis qui sinspire fortement de
Dynamo, utilise le protocole de bavardage pour maintenir ltat du cluster. Toute machine
qui joint ou quitte le cluster va lancer un message par bavardage. Les nuds changent
galement rgulirement leurs informations dappartenance, de faon sassurer quaucun
nud nait manqu une mise jour.
Le protocole de bavardage est aussi utilis pour grer la cohrence finale, comme nous le
verrons plus loin dans la section consacre la cohrence finale par nguentropie, page
88.

Le hachage consistant
Btir un systme distribu implique galement de partitionner les donnes pour les
distribuer de la faon la plus quitable possible entre les nuds. A priori, le moyen le plus
logique pour raliser cela est de se baser sur la cl (primaire) de la donne (par exemple,
lidentifiant du document), et de trouver un moyen, partir de cette cl, de distribuer les
donnes. Dans un systme sans matre, sans coordinateur, il faut aussi que les clients
puissent tre redirigs sur les machines qui contiennent les donnes voulues. Une rponse
basique ces problmatiques est la distribution des cls avec un modulo. En gnral, il
sagit dun hachage de la cl laide dun algorithme qui assure une bonne distribution du
rsultat et retourne une valeur entire, par exemple la mthode hashCode() quon trouve dans
toute classe Java et qui retourne un entier 32 bits. Pour notre dmonstration, nous allons
travailler directement avec un entier. Cette solution est illustre par la figure 3-5.

Figure 3-5
Distribution par hashcode

Ici, nous avons bti un systme distribu sur cinq nuds. Nous voulons distribuer nos
donnes de la faon la plus rgulire possible. Notre algorithme dattribution des donnes
est bas sur un modulo : lorsque nous crons un nouvel enregistrement, nous calculons un
modulo 5 par rapport la valeur de lidentifiant. Le reste de la division par cinq nous
retourne le numro du nud auquel nous allons attribuer lenregistrement. Lattribution au
bon serveur peut tre rsume par la ligne de code suivante :
server = serverlist[ hash(key) % len(serverlist) ]

Et par exemple, lenregistrement portant lidentifiant 48 sera envoy sur le nud 3. Cest
aussi simple que cela. Et, la rigueur, si le client est au courant du nombre de nuds, il
peut deviner lui-mme o se trouve lenregistrement quil cherche, car il connat la cl,
calcule le modulo et va directement sur le bon serveur. Mais en pratique, cette
connaissance du client pose problme, car cela implique de stocker trop de donnes de
configuration du ct du client, et cela fige le systme : comment, par exemple, faire
voluer la configuration du client quand on ajoute des nuds ?
Justement, que va-t-il se passer lorsquon va souhaiter ajouter un nud ? Nous devons
modifier notre modulo pour quil corresponde au nouveau nombre de nuds, mais cela
implique que lattribution dune majorit des enregistrements doit changer, comme illustr
sur la figure 3-6.

Figure 3-6
Ajout dun nud dans une distribution par hashcode

Cela veut donc dire qu lajout dun nud, une rorganisation des donnes doit se faire
sur tous les nuds. Cest un dfaut majeur, et sur un systme de grande envergure, cest
mme pratiquement inenvisageable. Cest pour viter cette problmatique que la technique
du consistent hashing a t dveloppe.
Lide du hachage consistant est dattribuer des ranges de valeurs pour chaque nud.
Conceptuellement, le systme distribu est vu comme un anneau (hash ring, anneau de
hachage), o chaque nud occupe une position sur lanneau. Chaque nud se voit
attribuer une valeur de hachage, qui dfinit la range de valeurs qui est hberge.
Lalgorithme de hachage calcule un hash code partir de la cl, trouve le nud dont la
valeur est immdiatement suprieure et y stocke la donne. Un nud contient donc toutes
les cls infrieures sa valeur de range et suprieures la valeur du nud prcdent,
comme illustr sur la figure 3-7.
Figure 3-7
Distribution par hachage consistant

Lorsquun nud est ajout lanneau, il prend une valeur de range, et donc scinde une
range existante. Lattribution des nuds ne sera donc trouble que pour une seule range,
et un nombre peu important de donnes sera dplac, comme illustr sur la figure 3-8.

Figure 3-8
Ajout dun nud avec hachage consistant
Choix du nud scinder
Quand le systme connat le nombre de cls qui sont gres par chaque nud, lattribution de la range dun
nouveau nud peut se faire automatiquement en scindant le nud le plus charg. Cest par exemple le cas avec
Apache Cassandra si vous utilisez le hachage consistant dans votre cluster.

Lune des premires utilisations du hachage consistant dans un cadre NoSQL est
documente par le site de partage musical last.fm dans une entre de blog datant de 2007
(http://www.lastfm.fr/user/RJ/journal/2007/04/10/rz_libketama_-
_a_consistent_hashing_algo_for_memcache_clients). La problmatique de distribution
des donnes que nous venons dillustrer se posait pour eux sur les serveurs memcached.
Afin dviter de redistribuer toutes les cls sur leurs serveurs de cache, last.fm a dvelopp
une bibliothque en C implmentant un algorithme de hachage consistant quils ont appel
Ketama. La bibliothque sappelle libketama, son code source est disponible sur un
serveur Subversion ladresse suivante :
http://www.audioscrobbler.net/development/ketama/. Le hash ring y est nomm le
continuum.
Une implmentation simple de hachage consistant pour Python est disponible dans le
module hash_ring (http://pypi.python.org/pypi/hash_ring/), qui peut tre utilis pour grer
lattribution de paires cl-valeur des serveurs memcached. Il est document sur cette
page de blog : http://amix.dk/blog/post/19367.
Exemple de hachage consistant : Redis

Conformment lesprit du logiciel libre, les moteurs NoSQL nont pas encore
implment toutes les fonctionnalits voulues. Il est cependant possible de les ajouter soi-
mme, ou de chercher un peu pour trouver une bonne me ayant dj fait le travail pour
nous. Lengouement du monde NoSQL fait quil gnre beaucoup de dveloppements et
dajouts. Nous allons en donner un exemple avec un module Python, nomm redis-shard.
Ce dernier implmente une API de sharding base sur du hachage consistant pour
distribuer une base de donnes Redis sur plusieurs machines. Pour linstant, la
clusterisation native de Redis est en dveloppement (les spcifications sont disponibles
cette adresse : http://redis.io/topics/cluster-spec). En attendant, une approche implmente
au niveau du client peut trs bien faire laffaire. Le concept peut sappeler du presharding
(http://oldblog.antirez.com/post/redis-presharding.html). Il sagit simplement dajouter
une couche au niveau de lapplication client qui distribue les donnes sur une liste de
serveurs Redis, afin de dcider avant lenvoi de la bonne destination. Le code source de
redis-shard est disponible sur le site github.com : https://github.com/youngking/redis-shard.
La configuration se fait en dfinissant une liste de serveurs disponibles. Par exemple :
from redis_shard.shard import RedisShardAPI

servers = [
{name:server1,host:192.1.68.30.10,port:6379,db:0},

{name:server2,host:192.1.68.30.20,port:6379,db:0},
{name:server3,host:192.1.68.30.30,port:6379,db:0},
{name:server4,host:192.1.68.30.40,port:6379,db:0}

Nous allons simplement reproduire ici une partie simplifie du code source, situ dans le
fichier hashring.py (https://github.com/youngking/redis-
shard/blob/master/redis_shard/hashring.py), qui montre comment raliser un hachage
consistant.
import zlib

import bisect
class HashRing(object):

Consistent hash for nosql API

def __init__(self, nodes=[], replicas=128):


Manages a hash ring.

self.nodes = []

self.replicas = replicas
self.ring = {}

self.sorted_keys = []

for n in nodes:
self.add_node(n)

def add_node(self, node):


self.nodes.append(node)

for x in xrange(self.replicas):
crckey = zlib.crc32(%s:%d % (node, x))

self.ring[crckey] = node
self.sorted_keys.append(crckey)
self.sorted_keys.sort()

def get_node(self, key):

n, i = self.get_node_pos(key)
return n

def get_node_pos(self, key):

if len(self.ring) == 0:
return [None, None]

crc = zlib.crc32(key)
idx = bisect.bisect(self.sorted_keys, crc)

idx = min(idx, (self.replicas * len(self.nodes)) - 1)


# prevents out of range index
return [self.ring[self.sorted_keys[idx]], idx]

def iter_nodes(self, key):


Given a string key it returns the nodes as a generator that can hold the
key.


if len(self.ring) == 0:
yield None, None

node, pos = self.get_node_pos(key)


for k in self.sorted_keys[pos:]:
yield k, self.ring[k]

Le constructeur de la classe HashRing remplit trois structures, dont le dictionnaire ring et la


liste sorted_keys. Cette dernire contient les valeurs de hachage qui forment les tapes de
lanneau, et ring attribue un nud ces tapes. Pour chaque nud de lanneau, le code
suivant est appel :
for x in xrange(self.replicas):

crckey = zlib.crc32(%s:%d % (node, x))


self.ring[crckey] = node

self.sorted_keys.append(crckey)

linstanciation de la classe HashRing, le membre replicas est initialis avec une valeur
entire. Il permet dindiquer un nombre de points virtuels afin damliorer la distribution
des donnes sur les nuds. La valeur par dfaut de replicas est 128. La fonction Python
xrange(), assez semblable la fonction range(), permet de crer une range utilisable dans
une boucle. Dans ce cas, xrange(128) retourne un objet numrable de 128 lments
numrots de 0 127. Pour chacun de ces lments, un crc est calcul et attribu ce
nud. Chaque nud aura donc 128 hachages qui pointeront sur lui. Le crc (cyclic
redundancy check) est gnr laide de la mthode crc32 de lobjet zlib (fournissant un
algorithme de compression compatible gzip), qui effectue un calcul de somme de contrle
assez basique et retourne une valeur entire 32 bits. Faisons un petit test de lutilisation de
cette mthode dans linterprteur interactif de Python pour nous familiariser avec lui :
python
Python 2.7.2+ (default, Jul 20 2012, 22:12:53)

[GCC 4.6.1] on linux2


Type help, copyright, credits or license for more information.

>>> import zlib


>>> import uuid

>>> id = uuid.uuid4()

>>> print id
96adc542-547a-488a-80ec-29c37a6d6fb7

>>> print zlib.crc32(id.bytes)

321027949

Nous avons ici import les modules uuid et zlib. Le module uuid permet de gnrer des
UUID (Universally Unique IDentifier) selon la dfinition du RFC 4122
(http://www.ietf.org/rfc/rfc4122.txt). Nous crons un UUID (96adc542-547a-488a-80ec-
29c37a6d6fb7) et nous passons sa reprsentation en chane de 16 octets ( laide de la
mthode bytes() de lobjet uuid) zlib.crc32(), ce qui retourne lentier 321027949. Simplissime.
Revenons au code de hashring.py. La recherche du nud concernant une cl est assure par
la mthode get_node(). Elle appelle la mthode get_node_pos() qui calcule le crc de la cl et le
passe dans la mthode bisect() du module bisect, qui offre un algorithme de maintenance
de tableau tri. bisect permet dajouter des lments un tableau tri sans avoir le trier
nouveau dans son intgralit chaque fois. La mthode bisect utilise dans la ligne :
idx = bisect.bisect(self.sorted_keys, crc))

emploie un algorithme de division (bisection) pour retourner un point dinsertion


directement droite (aprs) de la valeur de crc dans la liste self.sorted_keys, qui est la liste
des valeurs de crc attribues chaque nud dans la configuration du cluster redis-shard.
Cest donc exactement ce quil nous faut. Lindex est ensuite construit dans la ligne :
idx = min(idx, (self.replicas * len(self.nodes)) - 1)

La fonction min() retourne la plus petite valeur de la liste, cest--dire soit lindex retrouv
avec bisect, soit la dernire valeur dindex si celui-ci dpasse le nombre de points (nombre
de points virtuels nombre de nuds), le but tant videmment de grer les valeurs de crc
qui sont au-del de la dernire valeur du tableau de sorted_keys. Ladresse du nud est
ensuite retourne en le cherchant dans le dictionnaire ring :
return [self.ring[self.sorted_keys[idx]], idx]

Nous pensions quil tait intressant de vous montrer un algorithme simple de hachage
consistant pour vous permettre de mieux apprhender la mthodologie. Comme vous le
voyez, laide dun langage riche comme Python, limplmentation de hachage consistant
est aise et claire.

Les VNodes
Le hachage consistant est une bonne rponse aux problmatiques dlasticit dune
distribution des donnes de type DHT. Toutefois, il ne sagit pas forcment de la solution
la plus performante dans tous les cas. Une autre mthode existe, qui consiste dcouper
les donnes en nuds virtuels, et grer la rorganisation des donnes lors dun
redimensionnement du cluster par nud virtuel. Le terme VNode traditionnel est utilis
dans les systmes de fichiers UNIX pour dsigner un mcanisme dabstraction du systme
de fichiers, mais il est maintenant utilis dans un sens diffrent par Cassandra, et nous
avons dcid dans cet ouvrage de reprendre le terme spcifique de Cassandra pour parler
de la mthodologie sous-jacente.
Le hachage consistant prsente deux problmes. Tout dabord, lajout dun nud va
couper les donnes dun seul autre nud, ce qui ne contribue pas lquilibre gnral du
cluster. Tout au plus, cela peut rquilibrer un seul nud, ou rduire la charge relative de
ce nud et du nouveau par rapport aux autres. Lidal serait plutt une mthode qui
maintienne un quilibre gnral.
Par ailleurs, lchange de donnes entre les deux machines va fortement charger le nud
coup, qui sera donc sollicit en exclusivit, et le trafic rseau entre ces deux machines
subira un pic. Il faudrait un moyen qui, sans provoquer une migration aussi importante que
dans la technique du modulo, permette aussi de distribuer la charge de lalimentation du
nouveau nud. Cette technique, cest celle des nuds virtuels. Elle est maintenant utilise
par Cassandra en remplacement du hachage consistant, et elle est galement prsente dans
Couchbase Server.
La base de donnes va tre dcoupe, non pas en segments qui correspondent des
machines reelles, mais en beaucoup plus de blocs, qui seront rpartis sur les nuds.
Chaque bloc reprsentera donc une unit et chaque nud physique va hberger un nombre
proche de blocs. Lors de lajout dun nouveau nud, chaque machine va choisir un certain
nombre de ses blocs pour les envoyer sur le nouveau membre. Cela permet dassurer un
bien meilleur quilibre et de rpartir la charge rseau lors de la rorganisation du cluster.
Cela ne reprsentera pas de charge inutile, car seul le bon nombre de blocs sera dplac.

Rplication avec prise en compte de la topologie du rseau


Dans la section consacre la distribution matre-esclave page 72, nous avons abord le
sujet de la rplication matre-esclave et du sharding. Dans un systme sans matre, comme
les moteurs bass sur Dynamo, la distribution a les mmes contraintes, qui sont finalement
la transposition lchelle dun systme distribu des concepts dun systme RAID :
miroir des donnes pour assurer une redondance, et striping pour optimiser les lectures-
critures. Si nous prenons lexemple de Cassandra, les donnes y sont non seulement
distribues laide dun algorithme de hachage consistant, mais elles sont aussi rpliques
sur dautres nuds dune faon trs configurable. Comme nous venons de le voir, la DHT
de Cassandra maintient linformation du nud qui contient les donnes, mais aussi des
autres nuds sur lesquels ces donnes sont rpliques, et ces informations sont changes
par bavardage. Mais Cassandra permet aussi dindiquer une stratgie de duplication des
donnes incluant des paramtres de dispersion gographique, nomme le snitch (terme
dargot signifiant la balance ou linformateur). Ce snitch est indiquer dans le fichier
cassandra.yaml (situ dans le rpertoire /etc/cassandra/) sur le systme, dans loption
endpoint_snitch. On attribue comme valeur de snitch une classe qui implmente linterface
IendpointSnitch dans Cassandra. On peut donc crer sa propre rgle de rplication des
donnes. Les classes existantes sont listes dans le tableau 3-4.
Tableau 3-4. Snitches dans Cassandra

Classe Description

SimpleSnitch
Dans un dploiement sur un seul data center, cette classe privilgie la proximit
pour copier des rplicas.

PropertyFileSnitch
La proximit est dfinie par valeur de rack et de data center. Ces informations
doivent tre saisies dans le fichier cassandra-topology.properties.
Lidentification du rack et du data center local est ralise par inscription dans le
GossipingPropertyFileSnitch fichier cassandra-rackdc.properties. Cette information est ensuite
communique au cluster par bavardage.

RackInferringSnitch
La notion de rack et de data center est dduite de ladresse IP du nud. Le rack
correspond au troisime octet de lIP et le data center au deuxime octet.

Ec2Snitch
Cette classe peut tre utilise pour le dploiement sur un cloud Amazon EC2 dans
une seule rgion.

Ec2MultiRegionSnitch
Cette classe peut tre utilise pour le dploiement sur un cloud Amazon EC2 dans
plusieurs rgions.

Pour loption PropertyFileSnitch, un fichier de configuration de la topologie cassandra-


topology.properties placer dans le rpertoire de configuration, pourrait ressembler ceci :

# Data Center 1
192.168.10.10=DC1:RAC1

192.168.10.11=DC1:RAC1
192.168.10.12=DC1:RAC1
192.168.10.20=DC1:RAC2

192.168.10.21=DC1:RAC2
192.168.10.22=DC1:RAC2
# Data Center 2

192.168.20.10=DC2:RAC1
192.168.20.11=DC2:RAC1
192.168.20.12=DC2:RAC1

192.168.20.20=DC2:RAC2

192.168.20.21=DC2:RAC2
192.168.20.22=DC2:RAC2

# une valeur par dfaut pour les nuds inconnus

default=DC3:RAC1

Le fichier attribue les adresses IP des serveurs des positions de rack et de data center
(DC). Les noms de rack et de data center doivent ensuite tre dfinis dans la stratgie de
placement des espaces de cls de Cassandra, lorsquon en dfinit une.
Dfinir la stratgie de placement
La stratgie de placement tait auparavant dfinie dans le fichier de configuration cassandra.yaml. Depuis la
version 0.7.4, elle est prcise dans le systme despaces de cls (keyspace system) de Cassandra et la cration
dun espace de cls.

Par dfaut, deux stratgies de placement sont possibles dans Cassandra, comme indiqu
dans le tableau 3-5.
Tableau 3-5. Stratgies de placement

Stratgie de placement Description


org.apache.cassandra.locator. Simple, gre automatiquement par Cassandra.
SimpleStrategy
org.apache.cassandra.locator.
Prend en compte la topologie dfinie dans cassandra-topology.properties.
NetworkTopologyStrategy

La dfinition de la stratgie SimpleStrategy permet dindiquer un nombre de rplicas


maintenir pour lespace de cls. Par exemple :
CREATE KEYSPACE passerelles

WITH strategy_class = SimpleStrategy

AND strategy_options:replication_factor = 3;

cre lespace de cls passerelles en spcifiant que Cassandra doit maintenir trois rplicas
des donnes. La stratgie NetworkTopologyStrategy permet de spcifier les data centers
spcifis dans cassandra-topology.properties :
CREATE KEYSPACE passerelles
WITH strategy_class = NetworkTopologyStrategy
AND strategy_options:DC1 = 2 AND strategy_options:DC2 = 2;

Ce code cre lespace de cls passerelles en spcifiant que Cassandra doit maintenir deux
rplicas sur DC1 et deux rplicas sur DC2.
Cassandra est lun des moteurs NoSQL dont les possibilits de placement des rplicas sont
les plus affines. Riak, dans sa version Entreprise, est un autre exemple de moteur NoSQL
qui offre une fonctionnalit de rplication multi-data center.

La cohrence finale
Dans le chapitre prcdent, nous avons abord les problmatiques de cohrence
transactionnelle et dACIDit de la transaction. Nous avons vu galement que le thorme
CAP affirme, en un mot, quil est impossible de maintenir une transaction cohrente et une
bonne disponibilit dans un systme distribu. Il faut sacrifier une partie de lun des trois
critres pour augmenter les deux autres. Le choix le plus souvent effectu est
dabandonner la cohrence transactionnelle forte.
La rponse la cohrence dans un systme distribu, telle quelle se prsente dans les
moteurs NoSQL distribution asynchrone, sappelle la cohrence finale (eventual
consistency). Nous avons vu quun systme ACID ne rend pas ltat incohrent disponible
et quil bloque ou protge laccs aux ressources sales. La cohrence finale laisse le
systme ouvert, permet la lecture et soccupe au fur et mesure de diffuser les
modifications sur tous les nuds, en mettant en place des outils de rconciliation en cas
dincohrence. Il sagit dune forme de verrouillage optimiste.
BASE
travers ladoption du thorme CAP comme un axiome indpassable de la gestion transactionnelle dun serveur
de donnes, un jeu de mot a t cr pour dfinir lautre choix, savoir la cohrence finale. Il sagit du concept
BASE, pour Basically Available, Soft state, Eventually consistent.

Quand une requte arrive dans un moteur NoSQL, elle nest pas forcment sauvegarde
immdiatement. Elle peut tre conserve en mmoire ou tre applique sur une machine
sans tre immdiatement distribue sur dautres rplicas. La propagation des mises jour
seffectuera au fur et mesure.
Exemple de la propagation des DNS
Le mcanisme de propagation des DNS (Domain Name Server, serveur de nom de domaine Internet) est souvent
cit pour illustrer un systme de cohrence finale qui fonctionne. Lorsque vous voulez changer ladresse de la
machine sur laquelle pointe une URL (vous indiquez, par exemple, que http://www.babaluga.com pointe maintenant
sur ladresse IP 88.191.70.21), vous modifiez cette adresse dans un ou plusieurs DNS et vous indiquez auprs du
registrar du domaine que ces DNS sont autoritaires pour ce domaine.

Lorsquune machine sur Internet doit trouver ladresse IP correspondant


http://www.babaluga.com, elle demande la correspondance son DNS, qui va rpercuter
la recherche une hirarchie de serveurs DNS pour trouver le serveur autoritaire et
retrouver ladresse. Comme ceci peut prendre du temps, les serveurs DNS maintiennent un
cache local qui leur permet de rpondre plus rapidement. Cest ce cache qui est
potentiellement dconnect de la ralit la plus rcente. Ce cache se rafrachit
rgulirement, cest--dire que ses entres sont invalides aprs un temps nomm, le Time
To Live (TTL). un instant donn, une requte sur un DNS peut donc retourner des
rsultats obsoltes, mais terme (aprs cinq jours, au maximum), tous les DNS mondiaux
verront leur cache rgnr. Notons enfin que mme si on appelle traditionnellement ce
fonctionnement une propagation, il sagit ici plutt dun rafrachissement de cache en
mode pull que dune propagation en mode push.

La nguentropie et larbre de Merkle


Dans les moteurs NoSQL distribution dcentralise et asynchrone dont larchitecture
sinspire de Dynamo, comme Cassandra ou Riak, le protocole de bavardage est aussi
utilis pour rconcilier les donnes de faon ce que tous les rplicas obtiennent terme
la version la plus actuelle des donnes. Cest un systme nguentropique (dit aussi anti-
entropique, de langlais anti-entropy), qui permet la cohrence finale. On parle de systme
nguentropique en rfrence au terme invent par le physicien Erwin Schrdinger pour
dcrire la capacit des tres vivants maintenir un ordre malgr la tendance naturelle de
lunivers lentropie. Cette rconciliation et organisation des donnes sappuie sur la
technique de larbre de Merkle (Merkle Tree, aussi appel Hash Tree), qui est un
mcanisme de simplification de comparaison dun volume de donnes. Le concept a t
cr par Ralph Merkle, chercheur en cryptographie et en nanotechnologie, et brevet en
1982.
Imaginez que vous souhaitiez comparer deux bases de donnes qui sont supposes tre de
parfaits rplicas. Vous allez probablement le faire laide dun algorithme de hachage, un
checksum, par exemple en MD5, qui va produire un rsum dune valeur plus longue.
Vous allez produire un checksum de chaque ligne de chaque table, et comparer ces
checksums avec les mmes provenant de lautre base de donnes. Ainsi prsente,
lopration peut sembler longue et coteuse. Pour diminuer le travail, vous allez
probablement calculer le hachage dune table toute entire et effectuer la comparaison sur
cette seule valeur. Si les deux hachages correspondent, cela signifie que votre table est
identique. En revanche, si vous constatez une diffrence, vous pourrez descendre dans les
dtails en crant des hachages par pages de donnes, pour identifier les pages qui ont
chang, et ensuite en crant des hachages de chaque ligne dans les pages identifies, pour
retrouver les lignes modifies. Cest le principe simple de larbre de Merkle, beaucoup
utilis dans les systmes dchange de donnes en pair--pair, pour valider la cohrence
dun tlchargement. Ce principe est schmatis, pour un systme comme Cassandra, sur
la figure 3-19.

Figure 3-9
Larbre de Merkle

Il reste bien sr trouver le moyen de calculer cet arbre de Merkle au bon moment, en
minimisant limpact sur les performances. En Cassandra, par exemple, larbre de Merkle
est calcul par un validateur durant des oprations de compactage (voir la documentation
disponible ladresse suivante :
http://wiki.apache.org/cassandra/ArchitectureAntiEntropy).

Multi-Version Concurrency Control


Il reste un problme : comment grer les conflits ? Dans un systme distribu, on peut
mettre jour la mme donne rplique sur deux machines diffrentes en mme temps.
Comment prendre en compte ce cas de figure ? La rponse passe souvent par la gestion de
versions. Si nous prenons lexemple de CouchDB, il inclut un mcanisme de gestion de
versions (Multi-Version Concurrency Control, MVCC) permettant de grer un verrouillage
optimiste. Nous en verrons les dtails dans la partie II de cet ouvrage, Panorama des
principales bases de donnes NoSQL , mais esquissons-en dj ici les principes de base.
Chaque fois que vous enregistrez un document dans CouchDB, un numro de version est
automatiquement attribu par CouchDB, et visible dans un lment JSON nomm _rev,
prsent dans tous les documents. Il sagit dun UUID, comme illustr sur la figure 3-10
reprsentant linterface web de CouchDB, nomme Futon.
Figure 3-10
Futon

Vous voyez ici cinq documents, la cl est indique dans la liste de gauche, et la liste de
droite affiche le dernier numro de rvision. Il sagit bien dun UUID, auquel CouchDB
ajoute un compteur de version en prfixe. Ainsi, le document 1 a t modifi, puisque son
numro de rvision commence par 2-. Si nous entrons dans le document, nous voyons
quil est possible de naviguer dans les versions, les liens de navigation sont visibles en bas
de la fentre (figures 3-11 et 3-12).

Figure 3-11
Parcourir les versions dans Futon
Si nous cliquons sur le lien Previous Version, nous affichons la version prcdente, bien
sr. Notez le 1- au dbut du numro de rvision et ladresse de la page Futon visible dans
la barre dadresse du navigateur, qui indique en paramtre le numro de version

Figure 3-12
Version prcdente dans Futon

Ainsi, dans CouchDB, la cohrence est maintenue par les versions. Comme CouchDB est
nativement non distribu, cette version sert surtout assurer un verrouillage optimiste.
Lorsque vous mettez jour un document, vous devez indiquer le numro de version que
vous actualisez. Si le serveur CouchDB reoit une demande de mise jour dun document
qui nest pas la dernire version de ce quil a dans sa base, il refusera la mise jour avec
une erreur. Cest donc une forme de gestion de concurrence
Utilisation interne des versions
Il faut ici prciser un point : on pourrait se dire quil serait intressant de profiter de cette gestion automatique des
versions pour btir un audit historique des changements sur les documents. Cest bien entendu faisable, mais la
base, ce mcanisme de gestion de versions na pas t conu destination du client, mais bien pour la gestion
interne de la cohrence des donnes. Les anciennes versions sont de toute faon supprimes lors dun compactage
de la base CouchDB. Si ce ntait pas le cas, les besoins de stockage, qui ne sont dj pas ngligeables pour
CouchDB, seraient ridiculement levs : il faudrait maintenir en permanence un historique de tous les changements
sur les documents.

Mais les moteurs distribus peuvent aussi utiliser les versions pour grer la concurrence
finale.
Cohrence par timestamps

Dans le document de Google dcrivant sa base de donnes BigTable


(http://research.google.com/archive/bigtable.html), les donnes y sont dcrites comme un
dictionnaire index par une cl de ligne, une cl de colonne et un horodatage ( The map
is indexed by a row key, column key, and a timestamp ). Le modle est schmatis ainsi :
(row:string, column:string, time:int64) string
Cela veut dire quun horodatage est plac sur chaque couple ligne-colonne, donc chaque
cellule. Ainsi, lhorodatage est encore plus complet que celui propos par CouchDB. On
peut considrer chaque valeur stocke dans BigTable comme rfrence dans trois
dimensions : la ligne, la colonne et le temps. Le temps est exprim par une valeur entire,
qui reprsente la notion de timestamp dUnix : un nombre de secondes depuis une date de
rfrence (une epoch), qui correspond au 1er janvier 1970 minuit. Ce timestamp est
utilis par BigTable et ses clones (HBase, Cassandra, Hypertable) pour servir en interne
la rsolution de conflits et la cohrence finale. Il implique une contrainte : tous les
nuds et les clients doivent avoir leur horloge synchronise, car le client doit indiquer le
timestamp lors dune mise jour. Si plusieurs clients mettent jour la mme donne, cest
le timestamp le plus rcent qui verra son criture valide sur tous les nuds. Dans
Cassandra par exemple, o le timestamp est toujours indiqu par le client qui transmet
linstruction de mise jour des donnes, cela peut se rvler un rel problme.
Timestamp et horloge

On sait quune horloge dordinateur ne peut avoir la mme frquence que lunivers (on ne
va pas entrer dans le dbat de savoir ce que cela veut dire, surtout si on prend en compte la
relativit restreinte). Elle prsente en tout cas une forme de drive (clock drifting). Les
seules horloges qui approchent de la drive zro sont les horloges atomiques. Chaque
horloge dordinateur ayant une drive diffrente, mme si vous dfinissez un instant t la
valeur dhorloge de toutes vos machines, il se peut que quelques jours plus tard, celles-ci
affichent dj des diffrences de plusieurs secondes. Il est important dans un moteur
NoSQL qui sinspire de Google BigTable, comme Cassandra, dassurer une bonne
synchronisation de lhorloge.
NTP (Network Time Protocol) est le protocole historique matriser dans ce type de
systme. Il sagit dun outil qui va synchroniser lhorloge avec un rseau de serveurs NTP
hirarchique. Des pairs peuvent se synchroniser en rfrence des serveurs NTP un
niveau (appel stratum) suprieur. Les machines de rfrence auxquelles on se rfre
finalement sont typiquement des horloges atomiques ou des GPS (au stratum 0). Les
ordinateurs situs au stratum 1 sont relies directement aux horloges du stratum 0, et ainsi
de suite.
NTP doit tre install sur vos systmes en tant que service. Pour linstaller sur une
machine Debian ou Ubuntu, vous pouvez naturellement rcuprer le paquet qui se trouve
dans les dpts officiels.
sudo apt-get install ntp

Vous pouvez ensuite vrifier que le service a bien t dmarr.


Service ntp status

Sa configuration se gre dans le fichier /etc/ntp.conf, dans lequel vous indiquez les serveurs
de rfrence, soit des pairs, soit des machines un stratum suprieur.
NTP est un protocole complexe, notamment parce quil intgre des algorithmes
sophistiqus. Il ncessite donc un peu dapprentissage. Pour rester sur les choses qui nous
intressent, disons quil maintient un fichier de drive quil est utile de connatre. Sur
notre systme Ubuntu Server, il se situe ladresse /var/lib/ntp/ntp.drift. Ce fichier
contient lindication de la drive de lhorloge de la machine telle quobserve par NTP.
Cest une valeur exprime en PPM, ou Part Per Million, donc un millionime de seconde,
donc une microseconde par seconde. Si on fait le calcul, un PPM quivaut une drive de
86,4 millisecondes par jour.
Sur un systme UNIX, la commande suivante vous permet de faire directement le calcul,
en utilisant loutil bc, qui est un calculateur en ligne de commande.
echo cat /var/lib/ntp/ntp.drift*86.4 | bc

Sur notre machine, la valeur est 1398.556, soit 1,4 seconde par jour, ce qui est significatif
pour Cassandra. Imaginez quau bout dune semaine vous ayez une diffrence de dix
secondes par exemple entre deux machines : cela suffit craser des modifications
ultrieures par des modifications prcdentes cause dune erreur de timestamp.
Pour corriger cette drive, NTP va rgulirement raffecter lhorloge systme, en paliers
dans le cas o la diffrence avec lheure de rfrence est trop grande, pour viter de
provoquer des incohrences dans les applications qui maintiennent un journal, par
exemple. En fait, le but de NTP nest pas forcment de synchroniser, mais plutt de
discipliner lhorloge locale pour diminuer la drive.
Vous pouvez utiliser loutil ntpq pour requter ltat de NTP. En lanant :
ntpq -n

vous ouvrez un interprteur interactif qui attend vos commandes. Loption -n empche la
rsolution DNS des adresses de pairs, ce qui vous fait gagner un peu de temps.
Ensuite, la commande :
peers

vous montre la liste des machines qui sont requtes par NTP. Voici le rsultat sur notre
machine :

Il sagit des machines dfinies dans le fichier ntp.conf. Voici la description de chaque
colonne du tableau de rsultat.
Tableau 3-6. Rsultats de la commande peers

Colonne Description
Remote Adresse du pair ou du serveur qui est contact.
Refid Source de synchronisation de ce pair. Une machine un stratum suprieur.
St Stratum du pair. Ici, des machines au stratum 2.
T Type de pair : u pour unicast, m pour multicast, l pour local.
When Nombre de secondes depuis le dernier contact avec le pair.
Poll Intervalle de requtage vers ce pair en secondes.
Une valeur statistique daccessibilit du pair, assez obscure comprendre. Ici, notre valeur est le
Reach maximum : 377. Sur le binaire de 8 bits qui stocke cette valeur, cela correspond 11111111 en
octal (255 en dcimal). Donc succs sur les derniers huit appels vers ce pair.

Delay
Dlai en millisecondes pour obtenir la valeur du pair. Cette valeur doit naturellement tre
compense par NTP pour la mise jour de lhorloge locale avec la valeur rcupre du pair.

Offset
Diffrence de temps entre le pair et lhorloge locale, en millisecondes. Cest la valeur appliquer
lhorloge locale.

jitter
Appele aussi dispersion, diffrence maximale observe entre le pair et la machine. il sagit dune
bonne indication de la drive de lhorloge locale.

Vous pouvez aussi obtenir le statut de lhorloge locale avec la commande rv (pour readvar :
lecture des variables).
Rsultat chez nous :
associd=0 status=0618 leap_none, sync_ntp, 1 event, no_sys_peer,

version=ntpd 4.2.6p5@1.2349-o Wed Oct 9 19:08:06 UTC 2013 (1),

processor=x86_64, system=Linux/3.13.0-24-generic, leap=00, stratum=3,


precision=-22, rootdelay=43.308, rootdisp=66.116, refid=37.187.107.140,
reftime=d8680b75.ae96db62 Tue, Jan 20 2015 0:02:13.681,

clock=d8680bc5.65b80e89 Tue, Jan 20 2015 0:03:33.397, peer=30832, tc=6,


mintc=3, offset=-11.594, frequency=-13.000, sys_jitter=6.558,
clk_jitter=6.278, clk_wander=1.598

Nous avons mis en gras les valeurs importantes. Ce rsultat correspond ce qui est dfini
dans la spcification RFC 1305 de NTP version 3. Vous voyez le stratum, le temps actuel
de lhorloge, ainsi que le reftime qui reprsente la dernire fois o lhorloge a t
synchronise.
Vous pouvez ensuite quitter ntpq avec la commande exit.

Vector clocks
Si Cassandra utilise un horodatage simple, fourni par le client, pour grer la cohrence des
donnes, dautres systmes utilisent une mthode de gestion de versions interne,
implmente dans Dynamo de Amazon : la technique des vector clocks (tableaux
dhorloges). Cest le cas notamment de Riak.
Un timestamp tel que celui utilis dans Cassandra permet une gestion simple des versions,
mais cette dernire ne maintient aucune information de causalit. Il nest pas possible
partir dune colonne et de ses diffrentes versions, de savoir si une version est descendante
dune autre version, directement ou indirectement, ou sil sagit dune version parallle.
Cette information peut tre utile pour une gestion de rsolution de conflits plus
sophistique. Le vector clock permet cette distinction. Lalgorithme est simple : chaque
version est marque dune information de vector clock compose dun identifiant de nud
ou de processus (on pourrait dire, conceptuellement, un identifiant dacteur), et dun
compteur de versions. Le tableau 3-7 reprend lvolution du vector clock dune donne
depuis linsertion.
Tableau 3-7. volution dun vector clock

Action Valeur du vector clock


Nud1 insre une donne. Nud1:1
Nud1 effectue une modification. Nud1:2
Nud2 effectue une modification. Nud1:2, Nud2:1
Nud3 effectue une modification sur la version Nud1:2. Nud1:2, Nud3:1

Dans les deux dernires lignes du tableau, nous voyons que la version Nud1:2 est
modifie par deux autres nuds de faon concurrente. Grce au vector clock il est possible
den dduire quil y a un conflit, et de dfinir sur quelle version de la donne ce conflit se
produit.
Exemple dutilisation dans Riak

Riak utilise les vector clocks pour sa gestion de cohrence et de conflits. Le vector clock
est calcul par rapport lidentifiant de la machine cliente qui envoie linstruction. Nous
allons lexprimenter en utilisant son interface REST. Pour installer Riak et comprendre
son fonctionnement, rfrez-vous au chapitre 9 consacr Riak. Nous utilisons notre
bucket (lquivalent dune base de donnes dans Riak) Passerelles, dont nous modifions les
proprits de la faon suivante :
curl -v -XPUT -H Content-Type: application/json -d {props:{allow_mult:true,

last_write_wins:false}} http://192.168.0.22:8098/buckets/passerelles/props

Nous avons indiqu les deux proprits suivantes.


Tableau 3-8. Proprits du bucket

Proprit Description
allow_mult Vrai = permet le stockage de plusieurs versions de la mme donne.
last_write_wins Faux = conserve lhistorique des vector clocks.

Nous vrifions que les proprits ont t correctement enregistres :


curl -i http://192.168.0.22:8098/buckets/passerelles/props

Voici une partie de linformation de retour :


{props:{allow_mult:true,basic_quorum:false,big_vclock:50,chash_
keyfun:{mod:riak_core_util,fun:chash_std_keyfun},dw:quorum,last_write_

wins:false,linkfun:{mod:riak_kv_wm_link_walker,fun:mapreduce_linkfun},n_

val:3,name:passerelles,notfound_ok:true,old_vclock:86400,postcommit:[],
pr :0,precommit:[],pw:0,r:quorum,rw:quorum,sm

all_vclock:50,w:quorum,young_vclock:20}}

Ensuite, nous insrons un article de notre blog Passerelles :


curl -X PUT -H X-Riak-ClientId: Client1 -H Content-Type: application/json -d

{
auteur:

prnom:Annie,
nom:Brizard,

e-mail:annie.brizard@cocomail.com

},
titre:pourquoi les lphants ont-ils de grandes oreilles ?

} http://localhost:8098/buckets/passerelles/keys/1
En spcifiant une valeur manuellement dans len-tte X-Riak-ClientId, nous simulons lenvoi
depuis un client spcifique, ici nomm Client1. Rcuprons maintenant le document :
curl -i http://localhost:8098/buckets/passerelles/keys/1

Le retour inclut len-tte et le document. Nous reproduisons ci-dessous une partie de len-
tte.
HTTP/1.1 200 OK

X-Riak-Vclock: a85hYGBgzGDKBVIcBckcawMWufJnMCUy5rEyxNwTO8WXBQA=

Vary: Accept-Encoding
Last-Modified: Tue, 13 Nov 2012 14:19:39 GMT

Date: Tue, 13 Nov 2012 14:19:43 GMT

Content-Type: application/json
Content-Length: 223

Len-tte X-Riak-Vclock contient une version encode du vector clock maintenu par Riak.
Nous mettons ensuite jour :
curl -X PUT -H X-Riak-ClientId: Client2 -H X-Riak-Vclock:
a85hYGBgzGDKBVIcBckcawMWufJnMCUy5rEyxNwTO8WXBQA= -H Content-Type: application/json
-d

{
auteur:
{

prnom:Annie,
nom:Brizard,

e-mail:annie.brizard@cocomail.com
},
titre:Ce sont plutt les lapins, non ?

} http://localhost:8098/buckets/passerelles/keys/1

Nous avons envoy le vector clock reu dans len-tte, et nous avons indiqu un client
diffrent : Client2.
Vector clock dans len-tte
Le vector clock doit tre envoy dans len-tte, sinon Riak considre quil sagit dune premire version de la
donne, et la rcrit sans tenir compte dventuels conflits.

Essayons de crer un conflit en mettant de nouveau jour en mentionnant toujours le


premier vector clock dans len-tte, mais en spcifiant un client diffrent. Cela simule
donc une mise jour concurrente de la mme version depuis deux clients diffrents.
curl -X PUT -H X-Riak-ClientId: Client3 -H X-Riak-Vclock:

a85hYGBgzGDKBVIcBckcawMWufJnMCUy5rEyxNwTO8WXBQA= -H Content-Type: application/json

-d
{

auteur:

{
prnom:Annie,

nom:Brizard,

e-mail:annie.brizard@cocomail.com
},

titre:Ce sont plutt les livres, non ?


} http://localhost:8098/buckets/passerelles/keys/1

En requtant de nouveau notre article, voici ce que nous obtenons (sans len-tte) :
Siblings:

4dMeEvDd40iOTRivwn17sP
79rzSSGm3FLXgiTp37Lak1

Il y a maintenant deux versions concurrentes. La dernire insertion ntant pas un


descendant de la prcdente, Riak a conserv les deux versions et affiche un conflit.
Si nous relanons notre requte en indiquant dans len-tte HTTP au serveur que nous
acceptons les rsultats multiparts, de la faon suivante :
curl -i -H Accept: multipart/mixed http://192.168.0.22:8098/buckets/passerelles/

keys/1

nous obtenons le dtail des versions :


HTTP/1.1 300 Multiple Choices
X-Riak-Vclock: a85hYGBgzGDKBVIcBckcawMWufJnMCUy57EyOOlKnuLLAgA=
Vary: Accept, Accept-Encoding

Server: MochiWeb/1.1 WebMachine/1.9.0 (someone had painted it blue)


Last-Modified: Thu, 15 Nov 2012 09:09:22 GMT
ETag: 2XIl3pbcyiyPslEjWAkMwf

Date: Thu, 15 Nov 2012 09:18:03 GMT


Content-Type: multipart/mixed; boundary=VVvHewxojEOfURWT10ildkvVgim

Content-Length: 695
--VVvHewxojEOfURWT10ildkvVgim
Content-Type: application/json

Link: </buckets/passerelles>; rel=up


Etag: 4dMeEvDd40iOTRivwn17sP

Last-Modified: Thu, 15 Nov 2012 09:09:22 GMT


{

auteur:

{
prnom:Annie,

nom:Brizard,

e-mail:annie.brizard@cocomail.com
},

titre:Ce sont plutt les livres, non ?

}
--VVvHewxojEOfURWT10ildkvVgim

Content-Type: application/json

Link: </buckets/passerelles>; rel=up


Etag: 79rzSSGm3FLXgiTp37Lak1

Last-Modified: Thu, 15 Nov 2012 09:09:06 GMT

{
auteur:

{
prnom:Annie,

nom:Brizard,
e-mail:annie.brizard@cocomail.com
},

titre:Ce sont plutt les lapins, non ?

}
--VVvHewxojEOfURWT10ildkvVgim--

Pour rsoudre le conflit, il suffira de mettre jour la donne en indiquant le vector clock
renvoy (ici X-Riak-Vclock: a85hYGBgzGDKBVIcBckcawMWufJnMCUy57EyOOlKnuLLAgA=) pour craser les
deux versions en conflit, en faisant un choix au niveau de lapplication cliente.

Le Big Data analytique


Depuis le milieu de la dcennie 2000, notamment aprs la parution des articles de Google
dont nous avons dj parl, ce quon appelle maintenant le Big Data analytique a profit
dun fort dveloppement, avec Hadoop comme fer de lance.
On peut classer les orientations Big Data dans les mmes catgories que les bases de
donnes traditionnelles : oprationnelles et analytiques, OLTP et OLAP. Une base de
donnes oprationnelle vit et se trouve constamment modifie pour soutenir une activit
en perptuel changement. Les moteurs NoSQL qui permettent de monter en charge sur des
ptaoctets sont par exemple Cassandra ou HBase. Ils offrent des capacits de gestion et de
stockage des donnes semblables aux SGBDR, la diffrence prs quils sont
distribuables sur des milliers de machines, utilisant des concepts comme les tables de
hachage distribues (pour Cassandra) ou la distribution par consensus (HBase).
Ce sont des outils optimiss pour les critures et les lectures unitaires, non pas pour des
traitements massifs des donnes et des agrgations. Pour cela, vous devez utiliser une
approche analytique. La premire de ces approches a t et reste, cest toujours la
mthode principale MapReduce, sous linfluence de Google.

Le paradigme MapReduce
MapReduce nest pas en soi un lment de bases de donnes. Il sagit dune approche de
traitement de linformation distribue qui prend une liste en entre et en produit une en
retour. Il peut donc tre utilis pour de nombreux cas de figure et nous avons vu quil se
marie bien avec les besoins de traitements (comme des calculs) distribus des bases
NoSQL et les traitements dcisionnels.
MapReduce a t dfini en 2004 dans un article rdig par Google. Le principe est
simple : pour distribuer un traitement, Google a imagin une opration en deux tapes.
Tout dabord, une attribution des oprations sur chaque machine (Map), suivie aprs
traitement dun rassemblement des rsultats (Reduce). En soi, le raisonnement nest pas
rvolutionnaire. Encore fallait-il en dcrire limplmentation technique, de faon
suffisamment intelligente, pour viter les cueils propres un environnement distribu. Le
traitement distribu gnre des dfis comme : que faire en cas de dfaillance dune unit
de traitement ? comment sassurer dune bonne distribution du travail ? comment
synchroniser de faon efficiente les rsultats ? Le modle MapReduce offre des rponses
ces dfis avec la volont de simplifier et de contourner les problmes pour aboutir des
solutions pragmatiques.
Les besoins de Google qui ont donn naissance MapReduce sont de deux ordres :
comment traiter des volumes gigantesques de donnes dstructures (des pages web
analyser pour nourrir le moteur de recherche de Google, ou lanalyse des logs produits par
le travail de ses moteurs dindexation, par exemple), pour en tirer des rsultats de calculs,
des agrgats, des rsums bref, de lanalyse.
La diminution du cot du matriel ouvre la voie la rsolution du problme de lanalyse
du Big Data. Crer une architecture logicielle qui permette une monte en charge
horizontale simple est la rponse la moins coteuse au problme de la monte en charge.
Optimiser les performances dun systme de gestion de donnes sur une seule machine
demande beaucoup dnergie et de comptences, pour aboutir des rsultats fragiles qui
ne peuvent supporter une multiplication soudaine de la demande. En revanche, sassurer
que le modle de traitement des donnes est bien distribu de la faon la plus lgante
possible sur des machines spares, qui peuvent tre multiplies linfini, permet de
rpondre des augmentations foudroyantes de la demande de faon trs simple : par
lachat et linstallation rapide de nouvelles machines, quelles soient puissantes ou non, et
en sassurant que toute dfaillance dune machine ne se traduise pas par une perte de
donnes. Il faut donc vrifier que le modle dploy est capable de distribuer au mieux les
donnes et le travail, mme sur des dizaines de milliers de nuds, en offrant un systme
de rplication suffisant pour liminer statistiquement les risques de pertes de donnes.
Ce sont ces critres que le modle MapReduce permet de respecter. Il offre un modle qui
simplifie au minimum les complexits de linformatique distribue, en vue de fournir des
outils aux dveloppeurs. Limplmentation en Java donne par ailleurs la possibilit de
sabstraire de larchitecture matrielle, afin quun framework MapReduce puisse
fonctionner et interagir sur des machines htrognes.
Les oprations de map et reduce imagines par Google ont t inspires par les primitives du
mme nom du langage Lisp. Il est ici important de comprendre le modle de
programmation qui a donn naissance MapReduce.

Lisp et les langages fonctionnels


Lisp est lun des plus anciens langages informatiques. Il est cependant encore apprci de
nombreux dveloppeurs. Lisp se base sur un modle de programmation trs diffrent des
langages impratifs dont nous avons parl pour les opposer au langage dclaratif quest
SQL. Lordinateur et les langages impratifs sont bass sur le concept de machine de
Turing, o le traitement des donnes produit des changements dtat. un instant donn,
la machine a un tat, qui correspond lensemble des valeurs qui y sont places. Un
langage manipule cet tat et permet de le faire voluer travers un certain nombre
dactions. Un langage impratif manipule et modifie cet tat, en affectant des valeurs des
variables, par exemple. Le problme de cette approche est quun langage affectant en
permanence ltat du systme peut produire des effets de bord sur dautres sous-ensembles
de ce systme. Par exemple, si vous vivez en famille et que les membres de votre famille
qui remplissent le frigo ne sont pas toujours les mmes que ceux qui y puisent leur
nourriture, les effets de bord sont vidents : lise fait des courses et achte deux yaourts
pour les consommer dans quelques jours, mais entre-temps, William qui ouvre le frigo au
moment o il a un petit creux, mange dun coup les deux yaourts. Lorsque lise a faim
son tour, elle ne trouve plus de yaourts dans le frigo et ne peut se sustenter. Ltat du frigo
peut tre chang par plusieurs acteurs, il est donc en quelque sorte imprvisible pour
chacun dentre eux, et cela produit des effets de bord. On nest jamais sr de retrouver le
frigo dans ltat o on la laiss la dernire fois quon la ouvert.
La programmation fonctionnelle rpond ce problme en proposant un modle diffrent.
Ltat du systme global ne sera jamais altr. Les routines dun langage fonctionnel ne
modifient pas ltat gnral du systme, mais elles ne maintiennent quun tat transitoire,
propre chaque routine, et retournent des rsultats qui seront toujours manipuls de faon
locale. Pour cela, le modle principal de la programmation fonctionnelle consiste utiliser
des fonctions.
La fonction
En mathmatiques, une fonction utilise une variable et des paramtres constants pour retourner une valeur. Un appel
de fonction effectue donc un calcul dont le rsultat est retourn lappelant de la fonction.

Lapplication systmatique de fonctions permet de manipuler des donnes sans maintenir


un tat gnral, car aucun tat nest maintenu hors du temps dexcution de la fonction.
Pour cela, les mcanismes dexcution de ces fonctions sont privilgis dans les langages
fonctionnels. Par exemple, lappel rcursif des fonctions remplace la programmation par
boucle, ce qui permet de saffranchir de lutilisation de variables mutables (auxquelles on
peut affecter une nouvelle valeur). La programmation fonctionnelle offre la possibilit de
grer de faon trs souple et sre le flux de la donne, car aucun tat hors de lexcution
nest maintenu. Cela permet donc de rduire les effets de bord et de gagner en souplesse
au niveau du flux du programme, en acceptant par exemple plusieurs ordres dexcution.
Le langage Lisp est n dans les annes 1950 et se reconnat facilement par son nombre
lev de parenthses (au point que son acronyme est parfois transform en Lost In Silly
Parenthesis). Lisp manipule des listes, auxquelles des fonctions sont appliques.
lextrme, Scheme, un langage fonctionnel driv de Lisp, considre tout comme tant une
s-expression, cest--dire que Scheme ne fait aucune diffrence entre du code et des
donnes. Cela permet la cration de fonctions dordre lev, cest--dire des fonctions qui
acceptent dautres fonctions comme paramtres.

Un exemple de MapReduce en Lisp


Comme Lisp ne manipule que les listes, il a besoin dun mcanisme pour appliquer une
fonction chaque membre dune liste. Cette fonction sappelle Map. Elle retourne une
nouvelle liste dont chaque membre est modifi. Par exemple, le code suivant peut tre
excut dans le clbre diteur Emacs, qui est presque entirement crit en Lisp :
(require cl)

(map #list 1+ (1 2 3 4))

Tout dabord, nous ajoutons le module cl qui permet dinterprter des instructions crites
en Common Lisp au lieu de Elisp (Emacs Lisp) propre Emacs. Nous utilisons ici Emacs
comme interprteur Lisp car il est libre, facile obtenir et installer sur tous les systmes.
Lexcution de cette ligne dans Gnu Emacs ( laide de la combinaison de touches Ctrl +
Alt + X) retourne :
(2 3 4 5)

Nous avons appliqu lopration 1+ chaque membre de la liste, et nous recevons en


rsultat une nouvelle liste dont chaque membre est transform.
La fonction Reduce, aussi appele Fold dans dautres langages fonctionnels comme Haskell,
permet deffectuer un traitement sur chaque lment de la liste pour retourner une seule
valeur. Reduce utilise en interne un principe itratif : un accumulateur est dabord initialis.
La fonction Reduce est applique chaque lment de la liste et laccumulateur est
incrment. Le rsultat est la valeur de laccumulateur aprs traitement de chaque lment
de la liste. La ligne de code suivante, excute dans Emacs (aprs avoir ajout le module
cl comme prcdemment) :

(reduce + (2 3 4 5))

retourne simplement 14.


Ces deux fonctions ont donc donn des ides aux ingnieurs de Google. Pourquoi ne pas
appliquer les mmes principes de faon distribue ? Des fonctions Map sont appliques sur
un grand nombre de machines, gnrant comme rsultat des paires cl-valeur. Ces
ensembles de paires cl-valeur sont ensuite regroups et une fonction Reduce sapplique
combiner les valeurs qui appartiennent des cls identiques, pour retourner une valeur
agrge par cl. Cest un modle qui peut sappliquer un grand nombre de problmes.
Ce sont ces principes qui ont conduit llaboration de MapReduce. Un algorithme de
type Map traite une liste lment par lment, de faon isole. Cela rend donc possible une
excution en parallle et mme une excution distribue sur plusieurs nuds.

Le fonctionnement dHadoop MapReduce


Limplmentation libre de rfrence de MapReduce sappelle Hadoop. Nous en avons
parl : dveloppement par une quipe mene par Doug Cutting, en Java, pour les besoins
de son moteur dindexation distribu Nutch pour Yahoo!. Hadoop implmente directement
le document de Google sur MapReduce, et base son stockage distribu sur HDFS, qui
implmente le document de Google sur GFS. Rsumons : Hadoop est un framework
destin distribuer du traitement de donnes sur un nombre potentiellement illimit de
nuds.
Il est beaucoup plus efficace damener le traitement aux donnes que linverse. Cest la
mme ide qui est luvre dans les SGBDR : pour obtenir de bonnes performances avec
un moteur comme Oracle ou SQL Server, vous crez des procdures stockes qui
excutent le code de traitement au plus proche des donnes. Si vous rcuprez un large jeu
de rsultat pour le traiter sur votre client, les performances seffondrent.
Hadoop MapReduce vous permet dcrire des fonctions Map et Reduce en Java, et de les
envoyer sur des nuds de traitement. Ces machines comportent aussi un gestionnaire de
donnes (HDFS, HBase, Cassandra) que MapReduce va interroger pour rcuprer ses
donnes. Pour que MapReduce fonctionne, il faut que le traitement et les donnes soient
colocalises : on parle de localit des donnes. Le traitement seffectuant sur les donnes
locales chaque nud, le traitement sur les donnes est donc aussi efficace que celui
dune procdure stocke dans un SGBDR : on traite au plus proche des donnes.
Nous allons parler encore un instant de cette architecture, laide du schma trs simple
de la figure 3-13.

Figure 3-13
Architecture dHadoop MapReduce

Imaginons un traitement MapReduce avec des donnes stockes sur HDFS. Hadoop
MapReduce est bas sur une architecture matre-secondaire. Le matre, qui excute un
processus nomm le JobTracker, a la responsabilit de grer lexcution dune opration
MapReduce. HDFS est lui aussi bas sur une architecture matre-secondaire. Le matre
sappelle le NameNode. Cest la table des matires qui contient larbre des rpertoires et
des fichiers du systme de fichiers distribu. Cest donc lui qui sait o sont les donnes.
Le JobTracker contacte le NameNode pour savoir o se trouvent les donnes quil aura
traiter.
Les nuds secondaires MapReduce comportent des processus TaskTracker. Le JobTracker
envoie le code de traitement aux TaskTrackers libres qui sont au plus proche des donnes,
idalement en localit.
La responsabilit du JobTracker est de superviser le travail des TaskTrackers. Ceux-ci
vont renvoyer rgulirement un signal (un heartbeat) au JobTracker. Tout TaskTracker qui
ne se manifeste pas dans un dlai dfini est considr comme perdu, et son travail est
attribu un autre TaskTracker. De mme, le TaskTracker peut renvoyer une notification
derreur, et le JobTracker peut choisir dexcuter le code ailleurs et de marquer les
donnes ou le TaskTracker comme mauvais. Le JobTracker marquera la fin son statut
comme termin, ce que le client pourra savoir en interrogeant rgulirement le JobTracker.

Hadoop 2 YARN
Ce que nous venons de dcrire, cest un framework qui offre des fonctionnalits de
distribution dun traitement, Hadoop, et un type de traitement spcifique, MapReduce.
Tout le travail vers Hadoop 2, nom de code YARN (Yet Another Resource Negotiator), a
t de sparer ces deux lements.
Pour la sortie de la version 0.23 dHadoop, une grande rorganisation a t effectue. La
nouvelle version sappelle MapReduce 2.0 (MRv2) ou YARN. Le Jobtracker a t spar
en deux : un module de gestion de ressources (Resource Manager, ou RM) et un module
de traitement appel lApplication Master, ou AM.
Le Resource Manager coordonne le travail entre les nuds, sur lequels un dmon client,
nomm le Node Manager, gre lexcution locale du travail. Lexcution des fonctions
MapReduce est dlgue un dmon local spar, lApplication Master, qui utilise le
Resource Manager pour lexcution et la planification du travail.

Figure 3-14
Architecture dHadoop YARN

Le Resource Manager comporte lui-mme deux modules : dabord, un scheduler


responsable de lordonnancement des tches, dans le sens o il va simplement allouer des
ressources pour lexcution des tches. Cest un ordonnanceur gnrique pluggable. On
peut donc lui attribuer dynamiquement des algorithmes spcifiques dordonnancement.
Un exemple : lordonnanceur FairScheduler est un module dont lobjectif est dassurer
une distribution quitable des ressources sur le cluster dans le temps, en crant des files de
traitement. Une description du FairScheduler est disponible cette adresse :
http://hadoop.apache.org/docs/current/hadoop-yarn/hadoop-yarn-site/FairScheduler.html.
Pour linstant, il ny a que deux modules : FairScheduler et CapacityScheduler
(http://hadoop.apache.org/docs/r2.4.1/hadoop-yarn/hadoop-yarn-
site/CapacityScheduler.html).
Le scheduler est compltement agnostique vis--vis du type de traitement quil va prendre
en charge, tout comme lordonnanceur dun systme dexploitation ne sait rien de la
nature des processus quil place sur des processeurs. De plus, il ne soccupe que de
lallocation des ressources. La gestion du replacement des tches en cas derreur nest pas
de son ressort.
Les ressources en question sont pour linstant seulement de la mmoire vive. Cela va
voluer en incluant les autres types de ressources dune machine. Le Resource Manager
dfinit des containers, qui sont des units de ressources prsents sur un nud. La
distribution du traitement va soprer sur des containers sur des nuds.
Ensuite, le deuxime module du Resource Manager est lApplication Manager. Cest un
ordonnanceur de tches qui est en contact avec le code de traitement proprement dit.
LApplication Manager reoit la demande du client et lance lApplication Master. Ce
dernier est le gestionnaire du traitement spcifique, par exemple un travail MapReduce.
Cest lui qui va distribuer le traitement sur les containers mis disposition par le Resource
Manager.

Sparation des tches


Cette sparation entre deux modules, le RM et lAM, signifie donc que Hadoop YARN (le
RM) est un pur ordonnanceur de tches distribu qui est agnostique en matire de
traitement. Il permet de lancer nimporte quel type de tche, et non plus seulement du
MapReduce, qui devient un type spcifique dAM. Vous pouvez donc distribuer dautres
types de traitement que du MapReduce. Ces traitements prennent un terme plus gnrique
de DAG, ou Directed Acyclic Graph (graphe orient acyclique). Ce terme un peu
compliqu, qui emprunte la thorie des graphes, dcrit de faon gnrique un concept
simple : des nuds relis entre eux sans quils forment un circuit. Un DAG dans le sens
YARN, cest un traitement distribu qui peut contenir tout type de liaison entre les parties
du traitement. La liaison entre un traitement Map et un traitement Reduce est une forme de
DAG.
Mesos, le concurrent
YARN nest pas le seul environnement de traitement disponible. Sous la bannire Apache, vous trouvez aussi
Mesos, un gestionnaire de cluster dvelopp luniversit de Californie Berkeley, qui reprend conceptuellement
larchitecture du noyau Linux pour labstraire sur un cluster de machines. Il offre donc un environnement sur lequel
tourner du traitement distribu. Cest un projet trs actif et trs prometteur, qui savre un srieux concurrent de
YARN.

Hadoop 2 libre Hadoop de MapReduce et permet de btir Hadoop YARN et HDFS


comme un environnement de choix pour la distribution de tous types danalyses de
donnes Big Data.
On assiste aujourdhui une floraison dapplications qui se basent sur YARN, la plupart
donns la fondation Apache. Vous avez, avec ces applications, tout ce quil vous faut
pour changer et traiter vos ptaoctets de donnes de faon distribue, en batch ou en
temps rel.

Mode batch vs temps rel


MapReduce, cest un algorithme qui fonctionne en mode batch : il ny a pas de possibilits
dinterrogation interactive des donnes, ni de traitement immdiat de linformation.
Typiquement, comme pour lexemple canonique de lindexation dun moteur de recherche
comme Google, vous lancez un traitement planifi, qui prend le temps quil doit prendre,
et qui crit son rsultat dans un fichier, conceptuellement une vue matrialise du rsultat
de lanalyse des donnes. Cela peut prendre quelques heures. Il existe un concours annuel
de performance dexcution dun traitement de tri sur un cluster, dont vous trouvez les
rsultats sur le site http://sortbenchmark.org/. Par exemple, en 2013, le cluster Hadoop de
Yahoo! est parvenu trier 102,5 TO en 4 328 secondes sur un cluster de 2 100 nuds,
cest--dire en une heure et douze minutes. Plutt pas mal, cela reprsente une capacit de
traitement de 1,42 TO par seconde Regardez les rsultats 2014, Apache Spark va au
moins trois fois plus vite sur 207 nuds Amazon EC2. Nous reparlerons de Spark.
Mais, aussi impressionnant que soient ces performances, elles ne permettent pas de
rpondre des besoins comme un traitement en temps rel des informations : raction
automatique des situations mergentes, comme les tendances sur les rseaux sociaux, des
conditions actuelles de trafic autoroutier, des recommandations lutilisateur bases sur
son activit du moment, etc. En fait, au fur et mesure que le Big Data se dmocratise, ces
besoins se font de plus en plus pressants, et les exemples abondent. Du ct analytique,
cela ne permet pas lutilisateur de miner ou dinterroger ses donnes de faon
interactive, en excutant par exemple un langage dinterrogation ad hoc, comme HiveQL,
et dobtenir rapidement sa rponse, pour la modifier au besoin et renvoyer sa requte. Ces
deux besoins commencent maintenant tre couverts par des applications spcifiques qui
utilisent YARN ou Mesos comme couche de distribution. Par exemple, Apache Spark
offre des possibilits de requtage interactif et de traitement de flux en temps rel, et
Apache Storm est un systme de traitement de flux en temps rel la popularit
croissante. Nous tudierons plus en dtail ces outils dans la partie II du livre, lors de notre
exploration des diffrentes solutions NoSQL.

Le Big Data interactif


On pourrait tablir une loi pragmatique : pour savoir ce qui va se passer en Big Data,
surveillez les publications de Google (http://research.google.com/pubs/papers.html). En
2010, Google publie un article qui, une fois de plus, dcrit un systme dvelopp en
interne. Il sintitule Dremel: Interactive Analysis of Web-Scale Datasets (Dremel,
analyse interactive densembles de donnes de taille web). Ce systme garantit lanalyse
interactive de trs grands volumes en quelques secondes sur un cluster de traitement.
Dremel est bas dabord sur un stockage spcifique des donnes dans GFS. La structure
est dfinie comme un stockage orient colonnes pour des donnes imbriques (columnar
storage format for nested data). Le modle de donnes, dun point de vue logique, est
celui de Protocol Buffers (voir la section Les protocoles daccs aux donnes en dbut
de ce chapitre). Il sagit donc dune structure type, ordonne et hirarchique. Des
lments peuvent tre marqus comme obligatoires, optionnels ou rpts. On peut faire
rfrence une donne dans une structure protobuf laide dun chemin, comme on peut
le faire en XML ou en JSON.
Reprenons ici la structure que nous avions propose dans la section dcrivant Protobuf
page 59 :
message Article {

required int32 id = 1;
required string titre = 2;

message Auteur {

required string prenom = 1;


required string nom = 2;

required string email = 3;

}
repeated Auteur auteur = 3;

message Articles {
repeated Article article = 1;

}
Et crons un document de cette structure :
id: 1;
titre: Faut-il vraiment prendre des vacances ?

auteur:
prenom: Antoine

nom: Schmidt
email: aschmidt@passerelles.fr

auteur:

prenom: Pascale
nom: Chemin

email: pchemin@passerelles.fr

Le chemin dun e-mail dauteur, par exemple, peut donc tre exprim ainsi : auteur.email.
Chaque chemin est stock sparment dans des tables, de faon pouvoir y accder
indpendamment du reste du document. Un algorithme permet de reconstruire le
document partir des diffrents stockages parce que des informations de rptition et de
position sont ajoutes dans les tables. Grace ce type de stockage, il est possible de
reconstruire efficacement une partie du document sans accder au document tout entier,
pour les besoins de lanalyse.
Les donnes sont stockes dans GFS ou BigTable ; le langage dinterrogation est un driv
de SQL, qui travaille avec ce concept de tables imbriques, et qui retourne en rsultat de
nouvelles tables imbriques, cest--dire des structures dfinies en protobuf. La requte
descend un arbre dexcution, lequel passe dabord par une machine racine identifiant les
machines qui vont contenir les donnes requter, qui envoie la requte sur des serveurs
intermdiaires, qui envoient leur tour cette requte, etc., jusqu des machines au dernier
niveau, au plus proche des donnes, qui font le travail. Un module nomm le Query
Dispatcher distribue les diffrentes requtes et soccupe de la tolrance de panne, un peu
la manire du JobTracker dHadoop.
La fin du document de Google indique des statistiques de performances trs
impressionnantes, jusqu pouvoir parcourir 100 milliards de lignes par seconde.
Suivant lexemple des prcdentes publications de Google, cet article a montr la
communaut que linterrogation interactive des donnes prcdemment traites en mode
batch par Hadoop tait possible. Il ne restait plus qu commencer y travailler. Lune des
ralisations qui en a rsult sappelle Impala, dvelopp par Cloudera, une socit btie
autour dHadoop. Impala utilise un moteur dexcution de requte conu selon les
principes des moteurs relationnels, avec la possibilit dexprimer des jointures entre jeux
de donnes. Une autre implmentation libre toute frache sappelle Apache Drill
(http://drill.apache.org/), sortie durant lt 2014. Dans la vraie vie, le Dremel est un
moteur rotatif haute puissance, do le nom de Drill qui reprend cette ide. Drill
reprsente en interne les donnes provenant de diffrentes sources sous forme de
documents proches du JSON, ce qui se rapproche de la stucture protobuf dont nous venons
de parler. Un moteur de requte semblable celui de Dremel offre dexcellentes
performances et des connecteurs JDBC et ODBC permettent dutiliser Drill partir dun
langage client. Cest donc dans ce domaine que les avances sont les plus prometteuses
lheure actuelle.
4
Les schmas de donnes dans les bases
NoSQL

Comme nous lavons vu, le modle relationnel repose sur une stabilit du schma des
donnes, et donc sur une modlisation pousse, idalement complte, effectue au
pralable. Il est malheureusement difficile de respecter cette contrainte la perfection, et
nous ne nous souvenons pas avoir jamais rencontr un systme relationnel dans lequel le
schma tait rest invariant depuis sa premire mise en production. Les bases NoSQL
cherchent assouplir cette contrainte, gnralement en proposant une approche dite sans
schma , ou schma relax , ce qui veut dire quaucune vrification ou contrainte de
schma nest effectue par le moteur. Cest au dveloppeur qui utilise ces systmes de
dcider comment il organise ses donnes, et ceci dans son code client.

Le schma implicite
Dans les faits, il est quand mme difficile doffrir une totale libert. Par exemple,
MongoDB se dclare schema-less (sans schma), et en effet, rien nempche lutilisateur
de stocker des documents de diffrentes structures dans la mme collection. Toutefois, ces
documents ont un format structur (appel BSON), et il est fortement recommand de
conserver une structure homogne dans la mme collection, pour des raisons de logique et
notamment dindexation. Tout mlanger naurait aucun sens, comment effectuer une
recherche avec des critres communs ? Sur quoi placer un index ?
Le terme schema-less peut faire penser quun moteur NoSQL na pas de schma du
tout. Les moteurs purement paires cl-valeur peuvent prtendre cette appellation : ils
stockent une cl non type et une valeur opaque, purement binaire. On y met ce quon
veut. En revanche, les moteurs orients documents et orients colonnes maintiennent une
structure des donnes. Simplement, il ny a aucun contrle ou validation de cette structure
ct serveur. On parlera donc plutt de schma implicite. Dans ce modle, la
responsabilit de sassurer que le schma est correct est dporte dans le code client. La
responsabilit de la qualit des donnes incombe donc au dveloppeur, et non plus un
DBA de moteur relationnel.
Schema-less est un terme plus militant que descriptif. Toute donne complexe manipule
en programmation est une structure, elle a besoin dun schma qui dcrit cette structure.
Ce quon stocke dans un SGBD a donc un schma. La diffrence est que, contrairement
aux moteurs relationnels o le schma est explicite (contrl par le serveur) et fortement
structur, les moteurs NoSQL possdent un schma implicite et semi-structur.
Il est probable quavec le temps, les grands moteurs NoSQL intgreront des
fonctionnalits de validation de schma. Cest dj le cas de Cassandra 2, o la structure
des tables doit tre dfinie lavance quand on utilise CQL 3. En ce qui concerne les
documents, il existe une initiative pour dvelopper une validation du JSON : http://json-
schema.org/.
Pour le modle relationnel, les donnes sont importantes, et leur qualit ainsi que leur
organisation sont essentielles. Elles sont structures, contraintes, protges et cohrentes.
En stockant vos donnes dans une base NoSQL, vous leur accordez un crin diffrent,
plus permissif. Vous tes en quelque sorte comme un parent cool qui laisse la chambre de
ses enfants dans lordre quils souhaitent. Dans le monde de la base de donnes, les
enfants sont les dveloppeurs, et les donnes reprsentent la chambre.

Une approche non relationnelle


Par dfinition, le mouvement NoSQL, qui devrait, comme nous lavons vu, sappeler
plutt le mouvement non relationnel, schappe de ce qui fait le fondement des SGBDR :
les relations entre des donnes structures en tables, et donc les jointures ncessaires dans
le code de requte pour rejoindre les donnes selon leurs relations. Si vous tes familier
avec le modle relationnel, vous vous demandez peut-tre comment faire pour stocker les
donnes hautement rptitives dans un moteur NoSQL, par exemple les informations de
rfrence comme les lieux, les catgories, etc.
En fait, rien nempche de btir ses bases NoSQL selon au moins quelques principes
relationnels. Une base de donnes oriente documents, par exemple, rfrence un
document par une cl unique. Si vous considrez une base CouchDB ou MongoDB qui
contient un catalogue de DVD et une liste de commandes sur ces articles, le document
dtaillant la commande pourrait trs bien contenir la cl de la commande, comme illustr
sur la figure 4-1.

Figure 4-1
Relations dans une base de donnes documents

Vous viendrait-il lide de stocker nouveau dans chaque commande les informations
compltes des DVD achets ? cette question, la documentation de MongoDB rpond de
la faon suivante : il y a deux manires de considrer la situation. Soit vous faites de
lenchssement (embedding), cest--dire que vous intgrez des sous-documents dans le
document BSON, et donc vous dupliquez vos donnes, soit vous faites des liaisons
(linking), et dans ce cas, vous devez grer le drfrencement de ces liaisons dans votre
programme client. Le raisonnement est quune gestion de relations au niveau du serveur
serait difficile effectuer dans un environnement distribu. MongoDB Inc. est donc clair
ce sujet : la voie conseille est denchsser les documents. Est-ce toujours la chose
faire ? Sans doute, la rponse se trouve toujours au mme endroit : comment allez-vous
utiliser vos donnes ? Lenchssement des documents peut tre intressant si vous voulez
conserver un historique des produits. La duplication permet de conserver tout jamais
ltat du DVD au moment o la commande a t passe. De plus, il nest pas beaucoup
plus difficile de rechercher toutes les commandes du mme DVD avec un document
enchss ou li, si lidentifiant du DVD est maintenu de faon cohrente.

Les paires cl-valeur


Beaucoup de bases NoSQL partent du principe quune paire cl-valeur permet de rpondre
la quasi-totalit des besoins. Cette paire cl-valeur ressemble dailleurs ce quon peut
connatre dans une table dun schma relationnel si on le simplifie. Une table dans une
base SQL est compose dune cl primaire et dune ligne quelle identifie, ce qui pourrait
tre considr comme une valeur.
Notion de cls candidates
Cette comparaison, nous sommes forcs de le reconnatre, est un peu fausse, parce quelle ne prend pas en compte
la plus grande complexit du modle relationnel. Une table peut comporter plusieurs cls candidates, ce qui permet
didentifier une ligne partir de plusieurs cls, quelles soient appliques sur une colonne ou sur un ensemble de
colonnes.

Le raisonnement de la paire cl-valeur est que les besoins daccs aux donnes peuvent
tre simplifis ainsi : partir dune cl de recherche, je veux obtenir une donne
complexe. Voici quelques exemples dapplication de cette rgle.
Sur un site de rseau social, partir dun utilisateur (la cl), je veux obtenir une liste de
ses amis (la valeur).
Dans un catalogue de livres, le numro ISBN (la cl) donne accs tous les dtails sur le
livre (la valeur).
Dans un journal dactivits, la date dun vnement (la cl) indexe les dtails de ce qui
sest pass ce moment (la valeur).
Comme vous le voyez, la cl reprsente une information prcise et atomique, alors que la
valeur peut tre complexe et reprsenter un tableau ou une liste, elle-mme constitue de
cls qui pointent sur des sous-valeurs, et ainsi de suite.
Il sagit en fait dun modle bien connu, quon appelle souvent tableau associatif ou
dictionnaire dans les langages de programmation. Par exemple, en Python, un dictionnaire
se dfinit de la faon suivante :
#!/usr/bin/python
# -*- coding: utf-8 -*-
article = {} # ou dict()

print type(article)
article["auteur"] = {"prnom":"Annie", "nom":"Brizard", "e-mail":"annie.brizard@

cocomail.com"}
article["titre"] = "pourquoi les lphants ont-ils de grandes oreilles ?"
print article

Dans la plupart des pilotes de moteurs NoSQL dvelopps pour les langages clients, les
mthodes acceptent les structures de donnes du langage et les convertissent
automatiquement en structures du moteur, en protobuf ou Thrift par exemple.

Les entrepts cl-valeur


On peut opposer les entrepts, qui stockent spcifiquement des paires cl-valeur, aux
bases orientes documents, dont les valeurs sont des structures complexes comme des
documents JSON. Tous deux ont des cls, mais les valeurs contenues dans les entrepts
cl-valeur sont considres comme scalaires. Ces entrepts ont en gnral comme objectif
doffrir les meilleures performances possibles travers un dictionnaire.
Un des objectifs des entrepts cl-valeur est la simplicit. Il ny a vraiment plus de notion
de schma de donnes dans un tel systme. Chaque ligne peut tre compltement
diffrente des autres, et sil ny a pas de systme dindexation secondaire, le seul accs
valable est par la cl de la ligne.

Figure 4-2
Entrept cl-valeur

Les moteurs spcifiquement cl-valeur sont des clones de Dynamo, comme Projet
Voldemort ou Riak, et des descendants de memcached comme Redis (bien que Redis offre
un modle plus riche, voir chapitre 10).
On peut considrer que tous les moteurs NoSQL sont des entrepts de paires cl-valeur
plus ou moins spcialiss, et que les autres types de donnes que nous abordons dans ce
chapitre drivent du concept de cl-valeur. De mme, ces moteurs voluent souvent vers
un schma document de type JSON, en supportant lindexation secondaire. Riak et
Couchbase Server en sont des exemples.

La question de la redondance
Les bases NoSQL ne sont pas conomiques en espace disque : on peut le comprendre du
fait quil ny ait pas de relation entre les tables, et que les documents contiennent souvent
lintgralit des donnes travailler. Une base NoSQL sera susceptible de peser beaucoup
plus lourd que les mmes donnes stockes dans une base relationnelle bien normalise.
Cela ne gne pas les dveloppeurs et utilisateurs des bases NoSQL car labsence de
jointures leur parat un immense pas en avant vers les performances et la simplicit
(beaucoup de dveloppeurs naiment pas les jointures, probablement des utilisateurs de
MySQL, comme nous lavons vu). De plus, le stockage de masse tant relativement
accessible, les tailles importantes de donnes ne sont plus gnantes, en tout cas sur le
papier.
Le problme des performances en NoSQL diffre radicalement de ce quil est dans un
SGBDR. Un moteur relationnel tente doffrir les meilleures performances possibles dans
son contexte, en assurant une intgrit des donnes et une cohrence transactionnelle. Le
point de focalisation des performances dans un moteur relationnel se situe au niveau des
entres-sorties. Manipuler des donnes ne change pas tant les CPU, mais principalement le
systme de stockage. Cest autour de ce problme que ce sont construits les moteurs
relationnels, en offrant un modle qui permet dviter toute redondance de donnes, en
maintenant un cache des donnes en mmoire (le buffer pool), et parfois en offrant des
fonctionnalits de compression la vole des pages de donnes qui, dans la plupart des
cas, amliorent sensiblement les performances car le gain en I/O dpasse nettement
laugmentation de lactivit CPU.
Les moteurs NoSQL rpondent cette problmatique de faon trs diffrente. Labsence
de relation induit une surface des donnes beaucoup plus grande, car les informations sont
stockes de faon redondante. Il est bien sr possible de simuler des relations entre les
documents. Par exemple, on peut rfrencer la cl dune paire cl-valeur dans la valeur
dun autre document. Imaginons que nous devions grer un rseau social. Un document
peut contenir les informations dun utilisateur, avec sa cl (que ce soit son login ou une cl
numrique) et la valeur sera un document JSON stockant des informations sur ses choix,
ses activits et sa liste damis. Cette liste damis sera bien sr une liste de cls dautres
utilisateurs. Pour crer la liste damis, le code client devra retrouver le document de
lutilisateur, puis les documents des amis partir des cls. On pourrait considrer cela
comme une jointure qui signore, et il ny a finalement pas beaucoup de diffrence avec un
moteur relationnel, si ce nest que ce dernier effectue cette jointure au niveau du serveur
en utilisant un algorithme de jointure optimis, alors que le systme NoSQL va
probablement effectuer ces oprations en boucle, peut-tre avec des allers-retours du client
au serveur.
En ralit, si on sen tient purement aux moteurs eux-mmes, les systmes NoSQL sont
plus lents, parfois beaucoup plus lents, que les systmes relationnels, en fonction du type
de recherche (except les moteurs en mmoire comme Redis). Ils sont plus lents en
extraction, et parfois en modification. Paradoxalement, ils peuvent donner une impression
de plus grande rapidit parce quils distribuent la charge sur de nombreuses machines ou
quils dupliquent les donnes. Cest un peu la victoire des muscles sur lintelligence.
SGBD ou entrept de donnes ?
Ce nest peut-tre pas trs charitable de comparer les moteurs relationnels et NoSQL sur ces principes, mme si ce
sont eux qui ont commenc en se nommant NoSQL . Des outils comme Redis ou Riak ne se prsentent pas
comme des moteurs de bases de donnes mais comme des dpts (store). Le focus nest pas sur la manipulation et
la richesse fonctionnelle, ou sur les performances pures du moteur, mais sur le stockage et sur lutilisation en RAM
et la distribution de la charge de travail.

La cl et les recherches
Lorganisation des donnes en paires cl-valeur, la valeur tant scalaire ou un document,
pose aussi des problmes de performances si lon se place du point de vue de la base
relationnelle. Si le point dentre est une cl, cela signifie que la seule recherche efficace
passe par cette cl, car dans un moteur NoSQL, par dfaut, seule la cl est indexe. Dans
notre exemple de rseau social, nous pourrons rapidement accder aux donnes globales
dun utilisateur grce la cl.
Mais quen est-il des recherches partir dautres critres ? Dans un moteur relationnel, il
faudra soit effectuer un parcours (un scan), soit utiliser un index. Plusieurs moteurs
NoSQL comme MongoDB ou Riak 2i permettent de crer des index, souvent appels
index secondaires, quils soient en nouvelles paires cl-valeur ou en B-Tree. En ce qui
concerne la recherche par scan, qui consiste parcourir toutes les donnes pour tester la
valeur rechercher, elle nest en gnral pas implmente, sauf dans MongoDB, o ce
type de recherche est possible mais impraticable dans les faits cause de sa lenteur.
Indexation sur schema-less
Les principes dindexation se ressemblent, mais les moteurs NoSQL prsentent nanmoins une diffrence
importante avec les moteurs relationnels : leur schma de donnes est libre. Dans un moteur relationnel,
lindexation est aise parce que le schma est fix, et les colonnes sont visibles, en tant que mtadonnes, par le
moteur. Indexer une ou plusieurs colonnes revient, dans un moteur relationnel, dfinir un index sur des colonnes
bien connues. Dans un moteur NoSQL, personne ne sait si la valeur indexer dans un index secondaire est bien
prsente dans, disons, tous les documents dune collection. MongoDB, par exemple, permet la cration dindex
secondaires et ajoute des NULL dans lindex pour les documents qui ne contiennent pas la valeur indexer, ou les
ignore simplement si lindex est sparse.

Sans lutilisation de ces index, les recherches complexes (celles qui incluent un lment
qui ne constitue pas une cl ou plusieurs critres) se rvlent trs lentes dans la plupart des
systmes. Les seuls moyens disposition sont de travailler en mmoire ou de distribuer le
travail, deux mthodes qui sont dj utilises dans les moteurs relationnels travers le
buffer et le partitionnement des donnes. la rigueur, dans ce cas de figure, le
partitionnement dun moteur relationnel et le sharding dune base NoSQL sont
quivalents. La figure 4-3 prsente les diffrences entre un moteur relationnel et un moteur
NoSQL.
Figure 4-3
Partitionnement relationnel et NoSQL

Pour interroger un systme relationnel, vous envoyez une requte au serveur qui dclenche
un scan de la table. Le moteur de stockage paralllise les lectures sur les diffrents disques
physiques qui contiennent des partitions de la table. Si les donnes sont dj dans le
buffer, aucune lecture sur disque nest ncessaire.
Pour interroger un systme NoSQL tel que MongoDB, le client fait dabord appel au
superviseur ou au rpartiteur de charge (le dmon mongos dans MongoDB).
Systmes dcentraliss
Tous les systmes NoSQL nimposent pas un contrleur ou un point dentre unique. Riak, par exemple, est
compltement dcentralis. Cest pour cette raison que nous avons mis cet lment entre parenthses dans notre
schma.

Une fois les informations de sharding rcupres, le systme lance une suite de requtes
aux diffrents serveurs qui contiennent les shards rechercher. Cette fois, la rpartition
nest pas dcide par le serveur, mais au niveau du client qui lance les requtes et agrge
les rsultats. Ce mcanisme nest pas plus rapide que celui des bases relationnelles. Dans
un cas comme dans lautre, malgr la rpartition, le parcours sera coteux et il pourra
ltre parfois cause de la rpartition. Imaginez que vous lanciez une recherche sur un
MongoDB shard. La recherche seffectue sur une dizaine de machines, mais lune delle
a un problme technique ou est surcharge. Les autres machines auront retourn leur
rsultat et le client attendra sur la dernire pour clore son travail. Nous avons nouveau un
goulet dtranglement.

Les bases orientes documents


Les bases de donnes orientes documents prsentent une structure diffrente par rapport
aux bases en paires cl-valeur, principalement la structure de leurs lignes. Une base de
donnes dans un entrept orient documents peut tre compare une table dans un
SGBDR. La base contient des documents qui sont comme les lignes de cette table. Chaque
document contient en gnral une cl unique qui lidentifie. Les deux bases de donnes
orientes documents les plus populaires sont CouchDB et MongoDB.
Par documents , il ne faut pas entendre documents binaires. Au contraire, ces
documents sont structurs et lisibles par le moteur NoSQL. Le format privilgi pour le
document est en gnral du JSON, un format de dfinition de donnes qui contient une
structure hirarchique de proprits et de valeurs. Ces dernires peuvent tre scalaires ou
contenir des tableaux ou des sous-documents, et on peut souvent y attacher des fichiers
binaires (voir section suivante).
Un autre avantage des bases orientes documents est le versioning. Dans un moteur
relationnel, si vous devez changer la structure des tables pour faire voluer votre
application, vous devrez changer votre schma et faire des choses horribles comme ajouter
un numro de version dans le nom mme de la table. Par exemple, si vous avez cr une
table TarifIntervention en 2011, et que votre direction estime en 2012 que la gestion des
tarifs doit changer, vous allez probablement crer une table TarifIntervention2, parce que
vous devez maintenir en parallle lancienne et la nouvelle gestion des tarifs. La gestion
dune telle base de donnes deviendra de plus en plus complexe au fil du temps. Avec un
moteur de bases de donnes orient documents, vous pouvez simplement insrer des
nouveaux documents comportant les modifications de structure, et maintenir dans le
document un numro de version, qui sera test dans lapplication cliente pour une prise en
charge adapte.

JSON
JSON (JavaScript Object Notation) est un format de reprsentation de donnes
structures. Il a t cr par Douglas Crockford, un dveloppeur amricain trs impliqu
dans le dveloppement du langage JavaScript. Cest un format qui permet aussi bien de
srialiser ltat des classes que de structurer des donnes hirarchiques ou non. Cette
description devrait vous faire penser XML. En effet, JSON remplit le mme cahier des
charges que le langage XML, au moins son niveau basique. Il partage avec ce dernier
son format pur texte, donc reconnaissable sur toute plate-forme et par tout systme, la
capacit dexprimer des relations hirarchiques et la facilit de traitement (gnration et
parsing) automatis. En revanche et cest une des raisons pour lesquelles il est prfr
XML dans les bases NoSQL JSON est beaucoup plus compact, moins verbeux et
beaucoup plus simple lire et manipuler. XML est un langage de balisage qui drive du
langage SGML (Standard Generalized Markup Language, langage de balisage gnralis
standard). Il permet de dfinir la structure, et ventuellement le formatage de documents
potentiellement complexes, et de faciliter leur change et leur manipulation. XML est trs
intressant pour contenir et manipuler des documents, mais il peut tre un peu trop lourd
pour manipuler des donnes simples. La syntaxe et les structures de donnes de JSON, en
revanche, proviennent dun langage de programmation moderne, le JavaScript, ce qui en
est la forme norme. Avoir driv une notation de donnes dun langage de
programmation orient objet et dont la syntaxe, drive du C, est comprise par une
majorit de programmeurs, assure une proximit de ce format avec des structures
prsentes dans les langages de programmation eux-mmes, et donc une plus grande
simplicit de parsing par rapport au XML. De plus, en tant moins charg par lexpression
des mtadonnes, il est plus lisible lil nu.
Le code suivant est un exemple de document JSON bas sur notre application web de
test : un site dinformation communautaire nomm Passerelles, qui souhaite publier des
articles sur diffrents sujets, rdigs par les membres du site, et que les lecteurs peuvent
valuer et commenter. Ce document JSON stocke un article dont le titre est Pourquoi les
lphants ont-ils de grandes oreilles ? et qui comporte dj un commentaire.
{

auteur:

{
prnom:Annie,

nom:Brizard,

e-mail:annie.brizard@cocomail.com

},
titre:pourquoi les lphants ont-ils de grandes oreilles ?,
mots-cls:

[
faune,
afrique,

questions intriguantes
],
catgories:

[
sciences,
ducation,

nature
],
date_cration: 12/05/2012 23:30,

statut:publi,

nombre_de_lectures:54,
commentaires:

{
date:14/05/2012 10:12,

auteur:fred92@jmenmail.fr,

contenu:il ny a pas que les lphants qui ont des grandes oreilles !
}

Par comparaison, le mme document en XML donnerait quelque chose comme ceci :
<?xml version = 1.0 encoding = utf-8?>
<article>

<auteur prnom=Annie nom=Brizard e-mail=annie.brizard@cocomail.com />

<titre>pourquoi les lphants ont-ils de grandes oreilles ?</titre>


<mots-cls>
<mot-cl>faune</mot-cl>

<mot-cl>afrique</mot-cl>
<mot-cl>questions intriguantes</mot-cl>

</mots-cls>
<catgories>
<catgorie>sciences</catgorie>

<catgorie>ducation</catgorie>

<catgorie>nature</catgorie>
</catgories>

<date_cration>12/05/2012 23:30</date_cration>

<statut>publi</statut>
<nombre_de_lectures>54</nombre_de_lectures>

<commentaires>
<commentaire>

<date>14/05/2012 10:12</date>
<auteur>fred92@jmenmail.fr</auteur>
<contenu>[CDATA[il ny a pas que les lphants qui ont des grandes

oreilles !]]</contenu>
</commentaire>
</commentaires>

</article>

Formater du JSON
Les documents JSON retourns par les bases NoSQL ne sont bien entendu pas formats comme dans les exemples
de ce livre. Si vous souhaitez rcuprer un document JSON et le formater manuellement pour en faire un copier-
coller visuellement attractif, vous pouvez utiliser des formateurs JSON disponibles sur le Web. Citons par exemple
JSON Format (http://jsonformat.com/) ou JSON Formatter (http://jsonformatter.curiousconcept.com/).
Consultez le site http://www.json.org/json-fr.html, pour visualiser la liste des types de donnes reconnus par JSON.

Les bases orientes colonnes


Les bases de donnes orientes colonnes (Column Store ou Wide Column Store) sont assez
proches conceptuellement des tables relationnelles : elles comportent des colonnes avec un
type de donnes. La structure des bases orientes colonnes est modlise selon BigTable,
la base de donnes de Google.
Une table comporte des cls, souvent appeles rowkeys, les cls de lignes. Ces cls sont
uniques et sont maintenues dans un ordre lexicographique, cest--dire un tri binaire des
octets, sans interprter la valeur qui sy trouve, comme ce serait le cas dans un tri sur un
entier en 32 bits, par exemple. Le tableau 4-1 prsente des cls entires maintenues dans
un ordre lexicographique.
Tableau 4-1. Cls dans un ordre lexicographique

Cl
1
10
22
3
45
9

lintrieur de la table, des familles de colonnes sont dfinies et regroupent des colonnes.
La famille de colonnes est prdfinie, et on lui attribue souvent des options, alors que les
colonnes qui sy trouvent ne sont pas prdfinies, cest--dire quil ny a pas de
description de schma lintrieur dune famille de colonnes. Dune ligne lautre, les
colonnes prsentes dans une famille peuvent varier selon les donnes stocker.
Gestion des NULL
Dans une base relationnelle, la structure dune table est fixe lavance, et toutes les colonnes sont rfrences dans
chaque ligne. Si une valeur de colonne est inconnue, le SGBDR inscrit un marqueur NULL. Dans une base oriente
colonnes, la valeur non prsente ou inconnue nest simplement pas mentionne dans la ligne. De cette faon, elle ne
consomme aucun espace. Elle nest simplement mme pas prsente. Le schma varie donc de ligne en ligne.

Le stockage sur le disque est organis par famille de colonnes. On peut donc considrer les
familles de colonnes comme des sous-tables. Si on reprsente cette organisation du point
de vue de la structure des donnes quon peut manipuler dans un langage comme Java, on
peut voir les choses comme illustr la figure 4-5.

Figure 4-5
Structure du stockage orient colonnes

La table est un ensemble tri de cls. La cl est une liste de familles (cl = nom de la
famille, valeur = contenu), la famille un ensemble tri de colonnes, et la colonne une liste
de valeurs-timestamp. Cela donne en une ligne :
SortedMap<Cle, List<SortedMap<Colonne, List<Valeur, Timestamp>>>>

Les colonnes comportent donc un nom de colonne, une valeur et un horodatage


(timestamp), comme nous lavons dj vu.
Les bases orientes colonnes sont plus difficiles et complexes mettre en place que les
bases orientes documents ou paires cl-valeur, elles correspondent des besoins plus
larges, ce quon appelle le Big Data. Elles sont surtout dployes dans des compagnies qui
manipulent de trs importants volumes de donnes.
Leur stockage est autant que possible optimis : les familles de colonnes sont stockes
ensemble et compresses.

Les documents binaires


Les bases NoSQL peuvent tre plus intressantes que les bases relationnelles pour stocker
des documents binaires. Traditionnellement, le stockage de documents binaires a t une
problmatique vive des bases de donnes relationnelles. Nous avons vu que les moteurs
relationnels sont optimiss pour le traitement et la restitution des donnes discrtes, de
taille raisonnable et fortement types. Pour assurer de bonnes performances et une bonne
qualit de donnes, les principes de normalisation sassurent que les donnes sont les plus
atomiques possible. partir de cette organisation, le moteur de stockage dun SGBDR
organise le stockage sur disque en allouant des pages de donnes de taille fixe, qui
contiennent les lignes de table ou dindex. Cette organisation fonctionne bien pour des
donnes structures et trs mal pour des objets larges. Les utilisateurs de SGBDR ont donc
privilgi le systme de fichiers pour stocker les documents, en insrant simplement le
lien vers le fichier dans la base de donnes. Des mcanismes intermdiaires ont vu le jour,
comme le type DATALINK de la norme SQL7.
Comme les moteurs NoSQL ont une approche beaucoup plus souple et agnostique des
donnes stockes, il ny a thoriquement pas de raison dviter de stocker des documents
binaires directement dans le stockage de la base. Les interfaces daccs aux bases NoSQL
sont aussi plus souples que le langage SQL pour ce genre dapproche. Pour transmettre
des objets larges laide de requtes SQL, il faut raliser des contorsions laide
dextensions du langage. Les pilotes NoSQL sont en gnral beaucoup plus proches du
langage client et permettent denvoyer directement des objets. Plusieurs moteurs NoSQL
comme CouchDB ou Riak offrent galement des interfaces HTTP en REST qui permettent
denvoyer un document large. Comme ils sont conus pour stocker de larges volumes de
donnes de faon distribue, beaucoup les utilisent pour stocker des binaires sans
problme. Dautres moteurs, comme MongoDB ou Riak, offrent des couches spcialement
destines au stockage de binaires, comme GridFS pour MongoDB.
Pourquoi utiliser les bases de donnes NoSQL pour stocker des binaires plutt que de
passer pas le systme de fichiers ? Simplement parce quil est beaucoup plus difficile
dimplmenter un systme de fichiers largement distribu et redondant, ce quoffrent
nativement les bases NoSQL. Autant profiter de ces caractristiques pour les binaires
galement.

Le stockage du Big Data analytique


Depuis les premires implmentations des moteurs relationnels, les systmes de gestion
des donnes sparent clairement le stockage des donnes de leur traitement. La sparation
entre moteur relationnel et moteur de stockage dans les SGBDR permet disoler deux
responsabilits bien distinctes : linterprtation et lexcution de code de manipulation
(recherche et modification) des donnes, et la gestion physique du stockage et de la
cohrence. Pour aborder le Big Data analytique, cette sparation est galement importante.
Il faut clairement isoler les deux besoins pour btir une architecture solide.
Nous lavons vu, le paradigme MapReduce est bas sur la programmation fonctionnelle.
Si on dgage lessence de ce quon fait avec Hadoop, cest denvoyer des fonctions aux
donnes. Tout le framework Hadoop est simplement a : envoyer des fonctions (du code
compil, qui contient deux fonctions ou mthodes : map() et reduce()). La puissance de ce
modle, cest que vous avez pour vous toute la richesse du langage Java et ses
innombrables bibliothques disposition. Dans vos fonctions, vous pouvez donc faire tout
ce que vous voulez de vos donnes, et y accder quel que soit leur format, de simples
fichiers sur HDFS ou le contenu de bases de donnes comme Hbase.
Donc pour Hadoop, peu importe le stockage. Lorsque vous montez votre environnement
Big Data, vous allez choisir le modle ou le moteur de stockage qui rpond le mieux vos
besoins. Rien ne vous empche de stocker tout btement des fichiers CSV sur HDFS, ou le
contenu brut des logs que vous voulez analyser par la suite. Dans les faits, il faut quand
mme un minimum de structure. Nous allons aborder le sujet en prsentant quelques
formats adapts la galaxie Hadoop.

Les contraintes de stockage pour Hadoop


Vous pouvez trs bien travailler avec des fichiers bruts imports dans votre systme.
Attention, pour sassurer de bonnes performances avec Hadoop, il ne faut pas travailler sur
des petits fichiers. Lerreur ne pas commettre est daccumuler sur HDFS des fichiers
incrmentaux dimportation de donnes de quelques Mo ou dizaines de Mo et de travailler
partir de cette source pour les tches MapReduce. Cela pour deux raisons.
Premirement, HDFS nest pas du tout optimis pour travailler avec des fichiers de petite
taille, mais beaucoup plus apte grer des fichiers de grande taille. Lunit de stockage de
HDFS est le bloc, dont la taille est par dfaut de 64 Mo (129 Mo dans la configuration de
HDFS avec Hadoop). HDFS ne peut pas dposer plusieurs fichiers dans un bloc, il peut en
revanche dcouper un fichier de grande taille en plusieurs blocs. Si vous stockez une
grande quantit de fichiers de petite taille (on parle de Big Data, et par consquent de
grands volumes), vous consommez donc un grand nombre de blocs.
Cela ninflue pas sur le stockage effectif sur le disque physique, car HDFS ne
dimensionne pas ses fichiers reels sur la taille du bloc. En revanche, le Namenode (le
matre du cluster HDFS) conserve en mmoire un objet qui pointe sur chaque fichier et sur
chaque bloc, dont la taille est denviron 150 octets. Pour chaque fichier infrieur un bloc,
il lui faut maintenir en mmoire 300 octets pour le fichier et son bloc. Un million de
fichiers, cela veut donc dire 3 Go en mmoire sur le Namenode. Pour plus de dtails,
consultez cette entre de blog. http://blog.cloudera.com/blog/2009/02/the-small-files-
problem/.
Deuximement, les tches MapReduce ne travaillent pas avec plusieurs fichiers en mme
temps. Donc, charger une grande quantit de petits fichiers demande plus de tches
MapReduce, donc plus de nuds, et plus dattente sur des traitements squentiels, ce qui
se traduit par des diminutions importantes de performances. Il est donc important dviter
les petits fichiers.

Le problme avec HDFS


Il y a une autre dimension ce problme. la base, un fichier crit dans HDFS tait
immutable. HDFS ne supportait pas lajout de donnes lintrieur dun fichier existant.
Vous lcrivez, vous le supprimez, mais vous ne pouvez pas le changer. Noublions pas
que HDFS est conu en premier lieu pour stocker des donnes analytiques : on crit une
fois, on distribue le fichier sur le cluster, et on peut ensuite lire linfini, en parcourant les
fichiers plutt que par des accs alatoires comme ce serait le cas si on faisait une
recherche dans le contenu.
Les versions rcentes de HDFS implmentent la capacit dajouter des donnes la fin
des fichiers existants (donc faire un append). Mais il a fallu rsoudre des problmes
techniques. Devinez. Les mmes qui se posent dans les moteurs NoSQL distribus, cest-
-dire comment assurer la cohrence des fichiers rpliqus, comment revenir en arrire si
une criture se passe mal, etc. Il a donc fallu ajouter des tats supplmentaires dans
lalgorithmique de lcriture et mettre en place un systme de verrouillage. La
fonctionnalit a t distribue en 2008 dans la version 1.19.0 de HDFS, puis retire parce
quelle posait un certain nombre de problmes, puis ractive aprs correction dans la
version 0.21.0 (pour plus de dtails sur ce problme, vous pouvez vous rfrer la
demande HDFS-256 sur le Jira de la fondation Apache :
https://issues.apache.org/jira/browse/HDFS-265).
Lappend tant maintenant implment, il reste toujours une limitation : on ne peut
toujours pas raliser des modifications alatoires lintrieur dun fichier. On peut donc
crire des fichiers de type log (comme des structures LSM Log-Structured Merge-Tree
ou le journal de type write-ahead log de Hbase), mais pas maintenir des fichiers de
donnes bass sur une allocation diffremment structure.
Pour ces diffrentes raisons, il y a une petite histoire de rflexion et de solution autour du
meilleur moyen de stocker ses donnes pour les traiter avec Hadoop, Hive ou maintenant
des frameworks comme Spark. Une premire solution est bien sr de gnrer vous-mme
des fichiers plus importants pour les stocker dans HDFS. En gnral, vous manipulez des
donnes structures. Le CSV est une solution limite techniquement, le XML est trop
verbeux, le JSON peut faire laffaire, mais on peut esprer de meilleures performances.
Vous pouvez donc structurer vos fichiers avec Thrift, Protobuf ou Avro.
Mais attendez, vous avez en fait lembarras du choix. Plusieurs formats ont t conus
pour adresser ce besoin, il y a eu plusieurs initiatives qui ont dvelopp des solutions
maintenant largement utilises.

Le SequenceFile
En interne, Hadoop MapReduce doit changer des informations structures. Entre la phase
Map et la phase Reduce, les donnes doivent tre tries et envoyes aux reducers. Cette
phase sappelle Shuffle and Sort (dplacer et trier). Le format utilis en interne par Hadoop
pour ce faire sappelle un SequenceFile. Cest simplement un fichier binaire contenant des
paires cl-valeur.
MapReduce fournit une bibliothque qui permet trs simplement de travailler avec des
SequenceFiles, ce qui en fait un format trs utilis en entre-sortie pour des oprations
MapReduce. Le format est simple et dcrit dans la documentation dHadoop
(http://wiki.apache.org/hadoop/SequenceFile). Il peut tre compress ou non. La
compression est assure par un algorithme (nomm un codec) qui implmente linterface
org.apache.hadoop.io.compress.CompressionCodec. Les classes existantes implmentent la
compression en Zlib, BZip2, Gzip, Snappy : classes DefaultCodec, BZip2Codec, GzipCodec,
SnappyCodec (https://code.google.com/p/hadoop-snappy/). Comme son nom lindique, ZLib
est le codec par dfaut. Notons quun des avantages de BZip2Codec est quil permet de
dcouper le travail de compression/dcompression (il est splittable), et quil peut donc tre
mis en uvre en parallle par plusieurs tches MapReduce. Cela a son avantage sur des
fichiers de grande taille. On va y revenir.
Le fichier a bien sr un en-tte, qui indique notamment le codec de compression qui a t
utilis, puis un contenu, compos de paires cl-valeur, la valeur binaire tant compresse
le cas chant.
La classe org.apache.hadoop.io.SequenceFile (http://hadoop.apache.org/docs/stable/api/src-
html/org/apache/hadoop/io/SequenceFile.html) fournit trois sous-classes qui prennent en
charge la manipulation des fichiers : SequenceFile.Writer, SequenceFile.Reader et
SequenceFile.Sorter. Les noms sont autodescriptifs.

Voici un exemple trs simple de manipulation dun SequenceFile laide de lAPI


Hadoop, en Java :
Configuration conf = new Configuration();

Path path = new Path(/chemin_vers/sequencefile);


SequenceFile.Reader reader = new Reader(conf, Reader.file(path));
WritableComparable key = (WritableComparable) reader.getKeyClass().newInstance();

Writable value = (Writable) reader.getValueClass().newInstance();


while (reader.next(key, value)) {
// faites quelque chose ici;

}
reader.close();

Cet exemple correspond la manire classique ditrer dans une collection de donnes
provenant dun moteur de bases de donnes, laide dune forme de curseur.
Pour rsoudre le problme des petits fichiers que nous avons voqu plus haut, lune des
solutions les plus rpandues est dutiliser des SequenceFiles, qui sont conus pour a : les
fichiers sont encapsuls dans un fichier SequenceFile plus grand, le nom du fichier et
dautres mtadonnes au besoin sont inclus dans la cl, et le contenu du fichier est stock
et compress dans la valeur de chaque paire cl-valeur. Lavantage du SequenceFile est
quil est dcoupable par limplmentation de MapReduce : Hadoop est donc capable de
distribuer des parties du SequenceFile sur plusieurs tches MapReduce.

Le RCFile
RCFile (Record Columnar File) est une structure qui prend en charge le stockage distribu
de donnes tabulaires. Il a t dvelopp conjointement par Facebook, luniversit de
ltat de lOhio et lInstitute of Computing Technology de lAcadmie des Sciences
chinoise. En 2011, un papier a t publi et prsent lICDE 11 (International
Conference on Data Engineering) : RCFile: a Fast and Space-efficient Data Placement
Structure in MapReduce-based Warehouse systems Vous le trouvez facilement. Son
objectif est de remplacer les formats de stockage traditionnels (tabulaire, orient colonne,
etc.) afin dtre parfaitement adapt au traitement sur Hadoop. Lorsque larticle est paru,
RCFile tait dj utilis pour le dcisionnel de Facebook, ainsi quadopt dans Hive et
Pig, deux sur-couches analytiques pour Hadoop.
Les principes de base sont les suivants : les donnes sont reprsentes de faon tabulaire,
avec des colonnes et des lignes. Chaque ligne est conserve sur le mme nud. Le
partitionnement des donnes est donc effectu par ligne. En revanche, RCFile compresse
ses donnes pour des performances accrues, et il le fait par colonne, ce qui offre un
meilleur taux de compression (puisquune compression par dictionnaire applique sur les
donnes dune mme colonne trouvera plus de valeurs semblables rsumer que si on
appliquait une compression par ligne).
RCFile stocke ses tables dans des blocs HDFS, en composant des groupes de lignes (row
groups) dans chaque bloc. Les groupes de lignes sont toutes dune taille identique sur la
mme table, et un bloc HDFS peut en contenir plusieurs. Chaque groupe organise son
stockage en colonnes, cest--dire que les cellules sont regroupes et compresses par
colonnes. Outre lavantage en termes de compression, cela permet lors de la lecture pour
le job MapReduce de naccder quaux colonnes demandes par la requte. Le stockage
par colonne est particulirement bien adapt lanalytique, qui va traiter toutes les lignes
de la table, mais seulement les colonnes ncessaires lanalyse en cours. De plus, les
valeurs ne sont dcompresses que si la requte en a vraiment besoin (une fonctionnalit
baptise lazy decompression).
Requtes
Nous parlons ici de requte. RCFile est particulirement adapt aux outils de requtages par-dessus Hadoop comme
Hive ou Pig. En Hive, la demande est exprime en langage SQL (HiveQL). Une requte telle que SELECT produit,
quantite FROM ventes WHERE annee = 2008, entranera la rcupration seulement des colonnes produit,
quantite et annee, et la dcompression des donnes des colonnes produit et quantite qui correspondent lanne
2008.

Par ncessit nous venons de voir les limitations de HDFS , lcriture nest disponible
quen mode append, et la structure interne du RCFile doit se dbrouiller avec a.
Laccs aux donnes lintrieur des fonctions MapReduce se fait laide des classes
RCFileInputFormat, RCFileRecordReader et RCFileOutputFormat. Pour un exemple de code utilisant
Hive, vous pouvez vous rfrer cette entre de blog :
http://sumit1001.blogspot.fr/2012/01/rcfile-fast-and-space-efficient-data.html.

LORC File
Nous navons pas encore tout fait fini. Restons sur notre ligne chronologique. RCFile a
apport des optimisations bienvenues au stockage pour Hadoop, mais il restait quelques
imperfections. Dabord, bien que RCFile adopte un modle tabulaire, les colonnes ne sont
pas types. Elles contiennent donc des donnes purement binaires quil faut convertir dans
son application en entre comme en sortie. Cela peut avoir quelques dsavantages, par
exemple si on souhaite implmenter une indexation sur les valeurs, ou profiter de types de
compression adapts des types de donnes spcifiques. Limplmentation elle-mme de
RCFile pouvait encore tre amliore, notamment en ce qui concerne la recherche dans le
fichier et la compression.
Pour ces diffrentes raisons, un projet de la fondation Apache a cr une version amliore
de RCFile, nomme ORC File (pour Optimized Row Columnar File), spcifiquement pour
lintgration avec Hive. Lobjectif tait damliorer les performances et le stockage, tout
en prenant directement en charge les types de donnes manipuls par Hive, notamment les
types complexes comme les listes ou les maps, et les types de bases de donnes que Hive
reconnat en implmentant la norme SQL (Hive essaie par design de sapprocher de la
norme SQL-92).
Le format de fichier inclut des innovations, comme une sparation des groupes de lignes
en morceaux plus volumineux nomms stripes (256 Mo par dfaut), lajout dune structure
de fin (un footer, en plus donc de len-tte) au niveau des stripes et du fichier entier avec
quelques agrgats calculs sur les colonnes, ainsi quune indexation interne qui acclre
laccs aux groupes de lignes, en permettant dliminer des lignes parcourir par blocs de
10 000 lignes par dfaut.
Indexation
En maintenant les valeurs minimale et maximale de chaque bloc de 10 000 lignes, ces blocs peuvent tre limins
pour rsoudre une requte qui cherche hors de la plage de valeurs de ce bloc.

La compression est adapte chaque type de donnes stock dans les colonnes et elle est
optimise. Chaque colonne prsente plusieurs flux (streams) de donnes qui contiennent
non seulement la valeur de la cellule, bien sr, mais aussi des structures pour acclrer les
lectures. Par exemple, les colonnes de type string sont implmentes sous forme dun
dictionnaire, ce qui unifie chaque valeur et compresse dautant plus la colonne et acclre
les recherches sur les valeurs. Elles ont quatre streams : un stream de donnes (les valeurs
de la colonne), un stream de bits de prsence (pour dterminer rapidement si la colonne est
en NULL ou non), un stream des donnes du dictionnaire et un stream contenant la longueur
de chaque entre du dictionnaire.
ORC File est spcifiquement ddi Hive, et cest un ajout rcent Hive qui fait partie de
linitiative destine amliorer ses performances. Les gains de performances constats sur
Hive avec ORC File par rapport aux autres modes de stockage sont impressionnants. Vous
pouvez faire appel ORC File sans passer par Hive en utilisant Hcatalog.
Hcatalog
Sur des systmes analytiques, vous accdez aux donnes avec un modle deux ou trois couches : il vous faut un
outil de requtage, que ce soit MapReduce, Hive ou toute autre interface (elles fleurissent), et des donnes stockes.
Vous pouvez aussi utiliser une couche intermdiaire, une couche dabstration pour le format ou la structure des
donnes. On en connat beaucoup. Dans le monde relationnel, on pense aux univers de Business Object.
En Hadoop, on a dj Hive, qui remplit ce rle en offrant une reprsentation en tables relationnelles de donnes
stockes en HDFS. Hcatalog est une de ces couches dabstraction, qui reprsente sous forme tabulaire et
relationnelle des donnes sous-jacentes de fichiers plats sur HDFS, de SequenceFile, de RCFile ou dORC Files.
Pig et MapReduce peuvent utiliser Hcatalog comme source de donnes. En lutilisant, vous pouvez donc interfacer
Pig ou mapReduce avec ORC File.

Le format a t rcemment travaill pour amliorer encore les performances, en ajoutant


une vectorisation des valeurs pour pouvoir les analyser en mode batch laide de Hive. En
un mot, Hive est maintenant capable de rcuprer des lignes par groupes de 1024 et de
stocker les valeurs en mmoire dans des vecteurs (des tableaux de valeurs simples) pour
pouvoir les traiter beaucoup plus rapidement avec des algorithmes simplifis. Pour plus
dinformations, vous pouvez consulter la documentation de Hive cette adresse :
https://cwiki.apache.org/confluence/display/Hive/Vectorized+Query+Execution.

Parquet
Nous nen avons pas tout fait fini avec la qute pour le bon format de stockage sur
Hadoop, ni avec les formats de stockage tabulaire. En 2012, Twitter et Cloudera dcident
de travailler ensemble pour dvelopper un format de stockage tabulaire bas sur HDFS et
destin optimiser le stockage et les performances. Impression de dj-vu ? En juillet
2013, la version 1 de leur dveloppement sort, baptise Parquet. En 2014, Parquet rejoint
la longue liste des projets en incubation Apache (http://parquet.incubator.apache.org/), et
la version 2 de Parquet est depuis en dveloppement sous le giron de la fondation.
Parquet est premirement un format de fichier qui permet de stocker des structures
imbriques complexes en implmentant lalgorithme dcrit par Google dans son papier sur
Dremel. Nous avons dj parl de cet algorithme. Parquet est donc limplmentation libre
de cet aspect de Dremel et il est particulirement cibl pour linterrogation interactive des
donnes Big Data, principalement pour Cloudera en utilisant leur outil de requtage
nomm Impala (http://www.cloudera.com/content/cloudera/en/products-and-
services/cdh/impala.html).
Comme dans ORC File, la compression est choisie individuellement par colonne. Le
stockage interne nest pas tellement loign de RCFile, avec une stratgie de groupes de
lignes (row groups) et de stockage par colonne (column chunks) pour optimiser la
compression et laccs. Le pied de fichier (footer) contient les informations de
mtadonnes.
Le stockage est dfini par le projet parquet-format (https://github.com/Parquet/parquet-
format). Les mtadonnes du format de stockage sont encodes en thrift. En utilisant le
fichier thrift de dfinition, vous pouvez gnrer du code de gestion pour lire et crire en
Parquet. Dans les faits, ce nest pas ncessaire. Le projet parquet-mr fournit le ncessaire
pour utiliser directement des fichiers Parquet en MapReduce, tandis que le concept de
modles dobjet (object models) et ses implmentations de convertisseurs offrent dj les
passerelles ncessaires pour reprsenter les donnes Parquet en Thrift, Avro, Protobuf,
Hive, Pig, etc.
Parquet est un projet dj mature, trs intressant et prometteur. Cest un excellent moteur
de stockage considrer si vous dmarrez un projet Big Data analytique.
7. Voir par exemple : http://wiki.postgresql.org/wiki/DATALINK
Partie II

Panorama des principales bases de


donnes NoSQL

En regard de ce que nous avons appris dans le chapitre prcdent, nous allons prsenter
dans cette partie les diffrents types de bases de donnes NoSQL ainsi que les produits qui
ont t dvelopps autour deux. Nous ne parlerons que des implmentations libres, car
elles constituent de toute faon lessentiel des outils NoSQL utiliss par les grandes
socits. Chaque grand moteur NoSQL (MongoDB, Cassandra, HBase, etc.) fera lobjet
dun chapitre.
Nous tudierons ces SGBD NoSQL de faon pratique : nous verrons brivement comment
les installer, quels en sont les outils et les fonctionnalits dadministration, et comment les
manipuler. Pour cela, nous utiliserons un systme Linux, en loccurrence Ubuntu Server,
dans sa version 14.04 LTS (surnomme The Trusty Tahr). LTS signifiant Long Term
Support (maintenue long terme), cette version sortie en avril 2014 sera supporte par
Canonical jusquen avril 2019, ce qui assure une relative prennit nos propos.

Prliminaires
Pour montrer comment fonctionnent les diffrents moteurs NoSQL, nous utiliserons un
langage client lisible et facile comprendre par tout dveloppeur. Il sagit de Python, un
langage de script trs populaire. Il comporte maintenant des bibliothques dinterfaage
pour tous les serveurs NoSQL importants. Python 3.4 est install par dfaut dans Ubuntu
14.04. Depuis quelques versions, Ubuntu ninstalle que Python 3 par dfaut. La version 3
de Python apporte des changements trs importants qui ne sont pas encore supports par
toutes les bibliothques. Nous installons donc Python 2.7 pour une meilleure
compatibilit, le paquet sappelle simplement python. Par ailleurs, il nous faut installer pip,
un programme de gestion de paquets Python :
sudo apt-get install python

sudo apt-get install python-pip

Nous allons utiliser la technique denvironnement virtuel de Python pour ne pas impacter
linstallation de base. Les paquets dextension de Python que nous manipulerons peuvent
sinstaller soit dans le rpertoire systme (par exemple, /usr/local/lib/python2.7/site-packages
sur Ubuntu), soit dans un rpertoire propre lutilisateur, en crant une installation
virtuelle (vitualenv) de Python, dans son rpertoire $HOME. Toutes les bibliothques systme
et les excutables y sont reprsents par des liens symboliques, et les additions de paquets
y seront dposes, ils sont donc propres lutilisateur et ne troublent pas linstallation
systme. De plus, il ny a pas besoin dtre utilisateur root pour les ajouter. laide de pip,
installons virtualenv :
sudo pip install virtualenv

Ensuite, nous crons lenvironnement virtuel pour nos tests :


cd ~

mkdir python_env

cd python_env
virtualenv nosql

Nous voil prts dcouvrir les diffrents moteurs NoSQL !


5
Hadoop et HBase

Hadoop
Hadoop est un projet socle, dont on peut dire quil est lorigine dune petite rvolution
informatique, et qui ne concerne pas directement les bases de donnes. La naissance
dHadoop prfigure une liste de projets libres ns de publications de Google, notamment
MapReduce: Simplified Data Processing on Large Clusters (MapReduce : traitement de
donnes simplifi sur des clusters de grande taille, voir
http://research.google.com/archive/mapreduce-osdi04-slides/index.html).
Hadoop est un projet en constante volution. Comme nous lavons dj dit, il a subi un
changement important dans sa version 2, puisque lenvironnement de distribution des
tches a t spar de limplmentation de lalgorithme MapReduce. Au moment o nous
crivons ces lignes, la version stable est la 2.6.0, sortie en novembre 2014. Vous pouvez
toujours tlcharger la version prcdente avec MapReduce intgr dans la branche des
versions 1.2.

Installation
Cloudera, une socit qui se spcialise dans le service autour dHadoop, offre une
distribution de niveau entreprise de tout lenvironnement Hadoop, avec une version libre
(CDH) et une version entreprise commerciale. Nous allons utiliser la distribution libre ; au
moment o nous crivons ce chapitre, elle est en version 5.3.1 et intgre un certain
nombre doutils de la nouvelle gnration Hadoop. Linstallation de production sur
plusieurs nuds peut tre effectue avec un gestionnaire graphique que nous vous
recommandons. Nous allons vous indiquer la marche suivre pour raliser cette
installation. Nous vous prsenterons ensuite une installation diffrente, afin deffectuer
nos tests en mode pseudo-distribu, cest--dire en simulant un systme complet sur une
seule machine.

Installation de production
Note prliminaire
Installer Hadoop, HDFS et HBase nest parfois pas de tout repos. Comme linstallation denvironnements Java
complexes, vous pourrez tre amen rencontrer certains problmes lors du processus dinstallation. Mme avec la
distribution Cloudera, nous avons d rsoudre plusieurs problmes lors de notre installation en mode pseudo-
distribu sur une seule machine Ubuntu. Nous vous indiquerons quelques pistes de solution en encadr.

Nous nous rendons ladresse http://www.cloudera.com/content/cloudera/en/products-


and-services/cdh.html. Vous pouvez tester une version Live de CDH sans installation
cette adresse : http://go.cloudera.com/cloudera-live.html. Un bouton permet dinstaller
automatiquement la version 4 de CDH grce loutil Cloudera Manager (voir figure 5-1).

Figure 5-1
Tlchargement de Cloudera Manager

Nous cliquons sur le bouton pour lancer la procdure dinstallation en tlchargeant


Cloudera Manager.
64 bits obligatoire
Attention, Cloudera Manager ne fonctionne que sur un environnement 64 bits. Il vrifie aussi que vous utilisez bien
une distribution supporte. Pour notre exemple, nous linstallons sur Ubuntu Server 14.04 LTS.

Nous tlchargeons et excutons le gestionnaire sur notre serveur :


wget http://archive.cloudera.com/cm4/installer/latest/cloudera-manager-installer.bin

chmod u+x cloudera-manager-installer.bin

sudo ./cloudera-manager-installer.bin

Le gestionnaire dinstallation dmarre, tlcharge les paquets ncessaires et les installe.


Lorsquil a termin, nous pouvons continuer linstallation partir du manager lui-mme,
qui est une trs belle application web, dmarre sur le port 7180. Donc, par exemple pour
un accs en local, http://localhost:7180. Lutilisateur et le mot de passe par dfaut sont
admin. Une mise niveau vers la version complte est propose, nous restons sur la version
gratuite, qui contient vraiment tout ce dont nous avons besoin notre niveau.
Ltape suivante nous demande de spcifier ladresse des nuds. Il convient ici dindiquer
des noms de machines ou des adresses IP, spars par des virgules, ou dutiliser des motifs
dadresses IP. Pour notre exemple, nous indiquons ladresse de notre seule machine.
Attention bien mentionner une IP externe et non la boucle locale (127.0.0.1), afin que
HDFS ne semmle pas les pinceaux par la suite. Il est important que le rseau et le nom
de la machine soient bien configurs sur les nuds ds le dpart, pour que les noms de
machines et les IP publiques correspondent. Nous indiquons donc lIP publique de notre
machine, comme illustr sur la figure 5-2.
Figure 5-2
Ajout des noms dhtes

Nous cliquons ensuite sur Recherche pour permettre la validation du ou des nuds. Nous
slectionnons ensuite la version de CDH que nous souhaitons installer sur nos htes, soit
CDH4, la dernire version en date. Nous validons en cliquant sur Continuer.
SSH
Dans la mesure o Cloudera Manager effectue ces oprations via SSH, assurez-vous que le dmon SSHD tourne sur
vos serveurs. Si vous utilisez une distribution Debian ou Ubuntu, vous pouvez linstaller grce la commande :
sudo apt-get install openssh-server

Nous fournissons ensuite lidentifiant de connexion SSH pour tous les nuds. Il est tout
fait possible dindiquer root ou un compte qui a les privilges sudo sans mot de passe.
tre sudo sans saisir son mot de passe
Pour accepter quun utilisateur puisse lancer des commandes sudo sans mot de passe, vous devez lindiquer dans le
fichier /etc/sudoers. Pour modifier ce fichier avec lditeur par dfaut, lancez la commande :
sudo visudo

Ajoutez la fin du fichier une ligne avec le nom dutilisateur que vous voulez configurer. Pour notre exemple, il
sagit de lutilisateur rudi :
rudi ALL=(ALL) NOPASSWD: ALL

Pour lidentification du compte, nous avons eu des problmes par une approche par mot de
passe, nous avons donc opt pour une authentification SSH par cl. Pour ce faire, il faut
crer une paire de cls sur la machine cliente (votre ordinateur de bureau) avec la
commande suivante :
ssh-keygen -t dsa

qui va crer la cl prive et la cl publique dans des fichiers dont vous pouvez indiquer le
nom. Par dfaut, il sagit des fichiers /home/$USER/.ssh/id_dsa et /home/$USER/.ssh/id_dsa.pub.
Vous pouvez aussi protger la cl prive par un mot de passe (passphrase) que vous
devrez communiquer Cloudera Manager pour quil ouvre la cl prive. La cl publique
doit tre place sur le serveur, dans le fichier /home/$USER/.ssh/authorized_keys, $USER tant ici le
compte du serveur que nous allons utiliser. La cl prive sera utilise par Cloudera
Manager pour signer la demande, et la signature sera authentifie par le serveur en
utilisant la cl publique. Il sagit, comme vous le savez sans doute, dune mthode
traditionnelle dauthentification des clients SSH.
Les cls tant gnres, nous ajoutons la cl publique sur le serveur en utilisant un script
conu pour cela :
ssh-copy-id -i ~/.ssh/id_rsa.pub rudi@192.168.0.27

Nous avons ici conserv le nom de la cl par dfaut : id_rsa. Nous chargeons ensuite le
fichier .ssh/id_rsa dans linterface de Cloudera Manager, comme illustr sur la figure 5-3.

Figure 5-3
Saisie des identifiants de connexion SSH
Authentification par mot de passe
Si vous prfrez essayer lauthentification par mot de passe, assurez-vous au moins que le serveur SSH accepte
lauthentification interactive par clavier (keyboard-interactive). Si ce nest pas le cas, vous obtiendrez une erreur
dans le Cloudera Manager ( keyboard-interactive auth not allowed by server ). Les messages derreur sont
visibles dans le fichier de log situ ladresse /var/log/cloudera-scm-server/cloudera-scm-server.log.
Pour activer loption dauthentification dans SSHD, modifiez le fichier /etc/ssh/sshd_config comme suit :
ChallengeResponseAuthentication=yes

puis redmarrez le dmon SSHD :


sudo service ssh restart

la fin de linstallation, tous les paquets de lenvironnement sont installs, notamment


Hue, une interface web de gestion dHadoop, et Flume-ng, un outil de traitement de log en
MapReduce. Cloudera Manager affiche alors un rsum, puis demande de slectionner les
services installer et dmarrer (figure 5-4).
Figure 5-4
Choix de linstallation

Nous choisissons Tous les services : HDFS, MapReduce, ZooKeeper, HBase, Oozie et
Hue . Il convient ensuite de configurer les outils, principalement les rpertoires utiliss.
Pour notre dmonstration, nous conservons les valeurs par dfaut et nous cliquons sur
Continuer. Linstallation effectue la configuration (cration des rpertoires ncessaires aux
services dans HDFS) et le dmarrage des services. Si la configuration est correcte, aucun
problme nest rencontr.
Configuration du rseau
Au risque de nous rpter, soyez attentif la configuration de votre rseau, et notamment ladresse de vos
machines. Si le nom de vos nuds est li la boucle locale dans le fichier hosts :
127.0.0.1 nom_du_noeud

le dmarrage du service HDFS sera compromis.

Il est maintenant possible de grer le serveur et les services travers Cloudera Manager
(figure 5-5).

Figure 5-5
Cloudera Manager
Installation manuelle
Vous pouvez bien sr installer Hadoop manuellement pour obtenir la dernire version ou si votre distribution nest
pas supporte par ClouderaManager. La marche suivre est indique en annexe.
Installation en mode pseudo-distribu
Linstallation prcdente permet de mettre en place un systme avec plusieurs nuds.
Cloudera a galement prvu une installation en mode pseudo-distribu. Les instructions
compltes sont disponibles ladresse suivante :
https://ccp.cloudera.com/display/CDH4DOC/Installing+CDH4+on+a+Single+Linux+Node+in+P
distributed+Mode.
Reprenons notre exemple depuis le dbut.
YARN
lheure actuelle, deux distributions sont possibles : une traditionnelle et une autre utilisant une nouvelle
architecture de la couche MapReduce nomme YARN (MRv2). Nous allons utiliser la version traditionnelle, la
MRv1, pour MapReduce version 1.

Java

Avant tout, nous devons installer Java, le JDK 1.6 dont Hadoop a besoin. Plusieurs
mthodes sont possibles pour Ubuntu comme indiqu sur la page http://doc.ubuntu-
fr.org/java. Nous effectuons ici une installation manuelle. Nous tlchargeons donc
linstalleur depuis le site dOracle, puis nous linstallons :
sudo mkdir /usr/local/java

sudo cp jdk-6u35-linux-x64.bin /usr/local/java


cd /usr/local/java
sudo sh ./jdk-6u35-linux-x64.bin

La dcompression du JDK dans le rpertoire dmarre. Le JRE est dcompress dans le


rpertoire /usr/local/java/jdk1.6.0_35. Nous allons ensuite ajouter les variables
denvironnement ncessaires lexcution de Java. Nous pourrions les insrer dans le
fichier /etc/profile, mais sur Ubuntu, /etc/profile source des fichiers individuels contenus
dans /etc/profile.d/. Nous allons donc utiliser cette mthode en crant un fichier
jdk1.6.0_35.sh dans ce rpertoire :

sudo vim /etc/profile.d/jdk1.6.0_35.sh

Ici, nous utilisons lditeur Vim. Sil ne vous est pas familier, utilisez lditeur Nano qui
est plus simple. Si vous travaillez en environnement graphique, lancez Gedit ou tout autre
diteur de votre choix.
Nous crivons les lignes suivantes dans le fichier pour ajouter le rpertoire du JRE dans le
chemin et crer la variable denvironnement JAVA_HOME ncessaire lexcution des
applications Java.
JAVA_HOME=/usr/local/java/jdk1.6.0_35

PATH=$PATH:$HOME/bin:$JAVA_HOME/bin

export JAVA_HOME
export PATH

Nous indiquons ensuite Ubuntu quelle version de Java est installe et comment la
trouver. Il sagit ici dune spcificit Ubuntu qui nest bien sr pas requise sur une autre
distribution de Linux. La deuxime ligne indique Ubuntu que notre installation est
lexcutable Java par dfaut.
sudo update-alternatives --install /usr/bin/java java /usr/local/java/
jdk1.6.0_35/bin/java 1

sudo update-alternatives --set java /usr/local/java/jdk1.6.0_35/bin/java

Ces commandes crent un lien symbolique /usr/bin/java qui pointe sur /etc/alternatives/java,
lui-mme un lien symbolique sur notre binaire dans /usr/local/java/jdk1.6.0_35/bin/java.
Nous excutons ensuite la commande suivante pour recharger le fichier profile sans avoir
besoin de redmarrer Ubuntu :
. /etc/profile

Puis nous vrifions que la variable denvironnement JAVA_HOME est bien prsente :
printenv | grep JAVA

Ce qui doit retourner cette ligne :


JAVA_HOME=/usr/local/java/jdk1.6.0_35

Nous testons aussi en appelant lexcutable java :


java -version

Nous obtenons cette rponse :


java version 1.6.0_35

Java(TM) SE Runtime Environment (build 1.6.0_35-b10)


Java HotSpot(TM) 64-Bit Server VM (build 20.10-b01, mixed mode)

Cloudera

Ensuite, nous tlchargeons un paquet qui configurera les dpts pour la distribution de
Cloudera. Ce paquet dpend bien sr de votre distribution (Ubuntu Server 14.04 Trusty
pour notre exemple). Les liens sont disponibles sur le site de Cloudera ladresse
https://ccp.cloudera.com/display/SUPPORT/Downloads. Nous dposons tout dans un
rpertoire cloudera pour faire les choses proprement.
mkdir cloudera
cd cloudera

wget http://archive.cloudera.com/cdh4/one-click-install/precise/amd64/cdh4-

repository_1.0_all.deb
sudo dpkg -i cdh4-repository_1.0_all.deb

Le paquet ajoute les dpts et la cl PGP dauthentification de la source. Nous installons


ensuite le paquet Hadoop en configuration pseudo-distribue :
sudo apt-get update

sudo apt-get install hadoop-0.20-conf-pseudo

qui rcupre et installe toutes les dpendances. Une fois cela effectu et avant de dmarrer
Hadoop, nous devons formater le namenode (le service qui assure la coordination des
fichiers) de HDFS :
sudo -u hdfs hdfs namenode -format

Erreur JAVA_HOME
Ici encore, il est possible que vous receviez une erreur de type JAVA_HOME is not set . Si cest le cas, cela
signifie que le JAVA_HOME dfini dans les fichiers denvironnement de Hadoop ne pointe pas au bon endroit. Un bon
moyen pour rgler ce problme pour tout ce qui tourne autour dHadoop consiste mettre la bonne valeur de
JAVA_HOME dans le fichier /etc/default/bigtop-utils (voir http://bigtop.apache.org/). Pour notre exemple, nous
ajoutons :
export JAVA_HOME=/usr/local/java/jdk1.6.0_35

la fin du fichier.

Nous lanons les services HDFS pour viter le redmarrage :


for service in /etc/init.d/hadoop-hdfs-*
> do

> sudo $service start


> done

Nous obtenons le rsultat suivant :


* Starting Hadoop datanode:

starting datanode, logging to /var/log/hadoop-hdfs/hadoop-hdfs-datanode-ubuntu-server-

64-fr.out
* Starting Hadoop namenode:

starting namenode, logging to /var/log/hadoop-hdfs/hadoop-hdfs-namenode-ubuntu-server-


64-fr.out
* Starting Hadoop secondarynamenode:

starting secondarynamenode, logging to /var/log/hadoop-hdfs/hadoop-hdfs-


secondarynamenode-ubuntu-server-64-fr.out

Nous vrifions que HDFS est lanc laide de lutilitaire jps :


sudo /usr/local/java/jdk1.6.0_35/bin/jps

Nous crons ensuite le rpertoire /tmp dans HDFS :


sudo -u hdfs hadoop fs -mkdir /tmp
sudo -u hdfs hadoop fs -chmod -R 1777 /tmp

puis nous vrifions :


sudo -u hdfs hadoop fs -ls -R /

Nous obtenons alors :


drwxrwxrwt - hdfs supergroup 0 2012-11-20 18:23 /tmp

ce qui prouve que HDFS fonctionne.


Nous devons encore crer les rpertoires pour MapReduce dans HDFS et dmarrer les
dmons MapReduce. Il sagit de faire des copier-coller partir de la documentation
Cloudera. Nous listons simplement les commandes sans commentaire :
sudo -u hdfs hadoop fs -mkdir /var

sudo -u hdfs hadoop fs -mkdir /var/lib


sudo -u hdfs hadoop fs -mkdir /var/lib/hadoop-hdfs

sudo -u hdfs hadoop fs -mkdir /var/lib/hadoop-hdfs/cache

sudo -u hdfs hadoop fs -mkdir /var/lib/hadoop-hdfs/cache/mapred

sudo -u hdfs hadoop fs -mkdir /var/lib/hadoop-hdfs/cache/mapred/mapred


sudo -u hdfs hadoop fs -mkdir /var/lib/hadoop-hdfs/cache/mapred/mapred/staging

sudo -u hdfs hadoop fs -chmod 1777 /var/lib/hadoop-hdfs/cache/mapred/mapred/staging

sudo -u hdfs hadoop fs -chown -R mapred /var/lib/hadoop-hdfs/cache/mapred


for service in /etc/init.d/hadoop-0.20-mapreduce-*

> do

> sudo $service start


> done

jps doit maintenant nous retourner un JobTracker et un TaskTracker :


sudo /usr/local/java/jdk1.6.0_35/bin/jps

2099 JobTracker
1066 DataNode

1152 NameNode
2264 Jps

1248 SecondaryNameNode

2177 TaskTracker

Nous crons enfin le rpertoire utilisateur pour nos utilisateurs Linux :


sudo -u hdfs hadoop fs -mkdir /user/rudi
sudo -u hdfs hadoop fs -chown rudi /user/rudi

Tester lexcution dHadoop


Nous allons tester Hadoop en utilisant la collection dexemples. Elle est situe dans un
fichier .jar (une archive Java contenant des classes et dautres ressources, utilise pour
packager une application ou des bibliothques).
Nous allons utiliser un programme exemple situ dans le fichier .jar et nomm
WordCount (cf. http://wiki.apache.org/hadoop/WordCount). Comme son nom lindique, il
compte le nombre doccurrences de chaque mot dans les fichiers contenus dans un
rpertoire. Lexcutable lancer est $HADOOP_HOME/bin/hadoop. Utilisez la commande suivante
pour le localiser :
whereis hadoop

Dans notre installation ralise laide de Cloudera, il sagit de /usr/bin/hadoop. Il a t


ajout dans les alternatives, il est donc visible dans le path. Nous allons excuter Hadoop
en utilisant le compte hdfs cr par linstallation, et lancer le fichier .jar :
hadoop jar hadoop*examples*.jar

Installation manuelle
Si vous avez install Hadoop manuellement (voir annexe), prenez lidentit de lutilisateur hadoop et lancez
Hadoop sous ce compte, en utilisant sudo -u hadoop.

Si le fichier .jar est trouv dans le chemin, tout va bien, sinon vous recevrez une erreur
Java java.io.FileNotFoundException, ou ventuellement une erreur java.util.zip.ZipException.
Dans ce cas, cherchez lemplacement du fichier .jar, par exemple avec la commande :
find . -iname *example*.jar -print

dans le rpertoire . Pour notre exemple, le fichier et son chemin sont


$HADOOP_HOME
/usr/share/doc/hadoop-0.20-mapreduce/examples/hadoop-examples.jar. Lappel sera donc :

hadoop jar /usr/share/doc/hadoop-0.20-mapreduce/examples/hadoop-examples.jar

Si tout est correct, le fichier .jar retournera ce message :


An example program must be given as the first argument.

Nous allons travailler avec des fichiers texte rcuprs du site du projet Gutenberg, qui
propose des ouvrages numriss du domaine public. Afin de nous assurer dun corpus
suffisant, nous avons pris des uvres dAlexandre Dumas
(http://www.gutenberg.org/browse/authors/d#a492), comme Le Comte de Monte-Cristo ou
Le Capitaine Arena. 28 fichiers texte au total pour environ 17 Mo. Nous les avons dposs
dans notre rpertoire local ~/dumas/, puis nous allons les dplacer dans HDFS et les traiter
avec Hadoop.
hadoop fs -mkdir /user/rudi/input

hadoop fs -put /dumas/*.txt /user/rudi/input

Lanons dabord une commande pour lister tous les mots prsents dans les fichiers :
hadoop jar /usr/share/doc/hadoop-0.20-mapreduce/examples/hadoop-examples.jar wordcount
/user/rudi/input /user/rudi/output

La commande lance Hadoop en spcifiant le fichier .jar contenant le programme Hadoop


excuter, le programme WordCount, ainsi que le rpertoire dentre et de sortie dans
HDFS. Le rpertoire de sortie ne doit pas exister au pralable, il sera cr par le
programme. Il faut donc que lutilisateur qui lance cette commande ait les droits adquats
sur ces rpertoires, cest pourquoi nous utilisons ici /user/rudi, notre rpertoire personnel.
Lexcution est assez verbeuse. Voici le dbut :
12/11/20 18:43:50 WARN mapred.JobClient: Use GenericOptionsParser for parsing the
arguments. Applications should implement Tool for the same.

12/11/20 18:43:50 INFO input.FileInputFormat: Total input paths to process : 28


12/11/20 18:43:51 INFO mapred.JobClient: Running job: job_201211201828_0002
12/11/20 18:43:52 INFO mapred.JobClient: map 0% reduce 0%

12/11/20 18:44:12 INFO mapred.JobClient: map 3% reduce 0%


12/11/20 18:44:14 INFO mapred.JobClient: map 7% reduce 0%
12/11/20 18:44:31 INFO mapred.JobClient: map 10% reduce 0%

12/11/20 18:44:33 INFO mapred.JobClient: map 10% reduce 2%


12/11/20 18:44:34 INFO mapred.JobClient: map 14% reduce 2%
12/11/20 18:44:36 INFO mapred.JobClient: map 14% reduce 4%

Lexcution prendrait quelques petites secondes si nous excutions Hadoop sans HDFS
sur des fichiers locaux. Elle est nettement plus lente en mode pseudo-distribu en utilisant
HDFS, qui est vraiment destin tre utilis dans un environnement rellement distribu.
Voici la dernire information produite par notre excution :
Job complete: job_201211201828_0002

Counters: 32
File System Counters

FILE: Number of bytes read=8272152

FILE: Number of bytes written=21081811


FILE: Number of read operations=0

FILE: Number of large read operations=0

FILE: Number of write operations=0


HDFS: Number of bytes read=18066032

HDFS: Number of bytes written=1737633

HDFS: Number of read operations=56


HDFS: Number of large read operations=0

HDFS: Number of write operations=1


Job Counters

Launched map tasks=28


Launched reduce tasks=1

Data-local map tasks=28


Total time spent by all maps in occupied slots (ms)=384048
Total time spent by all reduces in occupied slots (ms)=180854

Total time spent by all maps waiting after reserving slots (ms)=0

Total time spent by all reduces waiting after reserving slots (ms)=0
Map-Reduce Framework

Map input records=439824

Map output records=2889149


Map output bytes=29028140

Input split bytes=3184


Combine input records=2889149

Combine output records=508042


Reduce input groups=140107
Reduce shuffle bytes=7722869

Reduce input records=508042


Reduce output records=140107
Spilled Records=1051934

CPU time spent (ms)=63220


Physical memory (bytes) snapshot=5985443840
Virtual memory (bytes) snapshot=27786665984

Total committed heap usage (bytes)=4100964352

Vous pouvez voir les statistiques dexcution pour les oprations de Map et de Reduce. Le
rpertoire destination a t cr et contient deux fichiers. Le premier est un fichier quon
pourrait appeler smaphore, vide, dont la prsence consiste indiquer ltat dachvement
de la tche. Pour notre exemple, il sappelle _SUCCESS. Le second fichier contient bien sr le
rsultat du programme WordCount. Il sappelle part-r-00000 et consiste en un simple fichier
texte, dont voici un extrait.
Carnava, 1
Carolina 1

Carolina, 10

Carolina. 1
Caroline 49

Caroline, 32

Caroline. 11
Caroline: 2

Caroline; 2

Caroline? 2

Les mots trouvs sont lists avec le nombre doccurrences. Cest une liste de paires cl-
valeur exporte ici en texte, spares par une tabulation.

Code source de lexemple


Le code source de lapplication exemple WordCount est disponible ladresse :
http://wiki.apache.org/hadoop/WordCount. Nous reproduisons ici le code dans son
intgralit car il est court et utile pour observer la simplicit de dveloppement dune
application utilisant les fonctionnalits MapReduce dHadoop.
package org.myorg;

import java.io.IOException;

import java.util.*;
import org.apache.hadoop.fs.Path;

import org.apache.hadoop.conf.*;

import org.apache.hadoop.io.*;
import org.apache.hadoop.mapreduce.*;

import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;

import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
public class WordCount {
public static class Map extends Mapper<LongWritable, Text, Text, IntWritable> {

private final static IntWritable one = new IntWritable(1);


private Text word = new Text();
public void map(LongWritable key, Text value, Context context) throws IOException,

InterruptedException {
String line = value.toString();
StringTokenizer tokenizer = new StringTokenizer(line);

while (tokenizer.hasMoreTokens()) {
word.set(tokenizer.nextToken());
context.write(word, one);

}
}

}
public static class Reduce extends Reducer<Text, IntWritable, Text, IntWritable> {

public void reduce(Text key, Iterable<IntWritable> values, Context context)

throws IOException, InterruptedException {


int sum = 0;

for (IntWritable val : values) {

sum += val.get();
}

context.write(key, new IntWritable(sum));

}
}

public static void main(String[] args) throws Exception {

Configuration conf = new Configuration();


Job job = new Job(conf, wordcount);

job.setOutputKeyClass(Text.class);

job.setOutputValueClass(IntWritable.class);
job.setMapperClass(Map.class);

job.setReducerClass(Reduce.class);
job.setInputFormatClass(TextInputFormat.class);

job.setOutputFormatClass(TextOutputFormat.class);
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));

job.waitForCompletion(true);

}
}

Aprs les lignes dimportation ncessaires des classes Java et Hadoop (org.apache.hadoop.*),
une classe WordCount est cre, elle reprsente lapplication. Elle dclare deux sous-classes
statiques drives des classes de base de Hadoop : Mapper et Reducer. Voici la signature des
classes (situes dans lespace de noms org.apache.hadoop.mapreduce) :
Mapper<KEYIN,VALUEIN,KEYOUT,VALUEOUT>

Reducer<KEYIN,VALUEIN,KEYOUT,VALUEOUT>

HBase
Intressons-nous maintenant HBase (http://hbase.apache.org/). Il sagit dun clone de
BigTable bas sur Hadoop et donc dun moteur distribu orient colonnes. La figure 5-6
illustre le modle de stockage de HBase.

Figure 5-6
Modle de stockage de HBase

Une table organise des donnes par rapport une cl, et contient des familles de colonnes,
qui comportent des colonnes versionnes par un horodatage (timestamp). Voyons plus en
dtail chaque lment.
La cl est le point dentre de la donne. En HBase, elle peut tre binaire. Chaque valeur
de cl est bien entendu unique, et les cls sont tries par ordre lexicographique (par
opposition un ordre numrique, ainsi 2 viendra aprs 10, par exemple).
Une famille de colonnes permet de regrouper un certain nombre de colonnes. Toutes les
colonnes de la famille sont stockes ensemble sur le disque, dans un HFile. Il est
possible de spcifier des options la famille de colonnes, comme la compression.
Une colonne contient une donne versionne, cest--dire que chaque valeur de colonne
est accompagne dun timestamp, qui peut tre attribu par le systme.
Le timestamp sert grer la cohrence finale, mais aussi grer ventuellement des
versions au niveau de la logique cliente. On peut indiquer que les colonnes doivent
maintenir un certain nombre de versions, et les versions prcdentes seront purges
automatiquement.
Le chemin pour trouver une valeur est donc le suivant :
Table Cl Famille Colonne Timestamp
Indiquer le timestamp dans la requte nest pas ncessaire. Par dfaut, vous recevrez la
version la plus rcente.

Architecture
HBase est pleinement conu pour tre distribu. Il se base sur Hadoop et HDFS pour
distribuer son stockage. Les tables sont shardes automatiquement et spares en rgions.
Cette sparation est gre par des serveurs de rgions (RegionServer). Tout dabord, la
table est contenue dans une seule rgion. Lorsque la taille dune rgion dpasse un seuil
prdfini, HBase dcoupe la table en deux rgions, de tailles approximativement gales,
sur une valeur de cl correspondant la moiti environ de la range sparer. Cest une
opration rapide. Chaque rgion grera donc une range contigu de cls.
HBase comporte plusieurs dmons. Le tableau 5-1 explique brivement ces lments.
Tableau 5-1. Les dmons de HBase

Dmon Description
RegionServer Dmon de gestion des rgions, lesquelles permettent de distribuer les tables.
Service centralis de maintenance de configuration et de synchronisation pour les applications
ZooKeeper distribues (http://zookeeper.apache.org/). Cest le pendant du Chubby de Google. Il sert
maintenir ltat des nuds, promouvoir un nouveau matre si le courant est tomb, etc.

HMaster
Le dmon HBase, le moteur de bases de donnes lui-mme. Un HMaster gre plusieurs
RegionServers et centralise la gestion dun cluster HBase.

Structure des critures


Les donnes crites sont gres dans un WAL (Write-Ahead Log) et dans un buffer
mmoire nomm le memstore. Lorsque le memstore a atteint une taille dfinie, il est crit
sur HDFS dans un HFile, un ensemble tri de cl-valeur srialis sur disque, immutable,
crit en une fois partir du memstore.
Fonctionnement des suppressions
Si le HFile est immutable, comment les suppressions sont-elles gres ? Grce un mcanisme de marqueurs
nomms tombstones. La suppression nest pas effective immdiatement, elle sera effectue au compactage en se
rfrant aux marqueurs de suppression.

La rduction des diffrents HFile dune famille de colonnes est effectue par une phase de
compactage. Cette structure est classique des descendants de BigTable, et nous la
retrouverons pratiquement lidentique quand nous tudierons Cassandra.
Ainsi, les rgions assurent la distribution, HDFS la rplication.

Installation en mode standalone


Il ny a pas vraiment dintrt faire fonctionner HBase en mode pseudo-distribu. Nous
avons dj montr un exemple de mode pseudo-distribu pour Hadoop, le principe est le
mme, HBase se base sur HDFS. Si vous devez utiliser HBase en production, vous le
ferez en mode pleinement distribu. Installons-le partir des paquets Cloudera, en mode
standalone :
sudo apt-get install hbase-master

Linstallation doit faire dmarrer le dmon. Dans le cas contraire, vous pouvez le dmarrer
manuellement :
sudo service hbase-master start

Les choses sont simplifies ici car en mode standalone, le serveur de rgion et ZooKeeper
sont excuts en interne par HMaster. En mode distribu, vous devez les configurer et les
lancer indpendamment.
Rsolution des problmes dinstallation
Si vous rencontrez des problmes lors de vos premires installations dun lment de la pile Hadoop, la premire
chose faire consiste consulter les logs. Dans la distribution Cloudera, le log de HBase se trouve dans
/var/log/hbase. Rsolution des problmes dinstallation

Si vous rencontrez des problmes lors de vos premires installations dun lment de la
pile Hadoop, la premire chose faire consiste consulter les logs. Dans la distribution
Cloudera, le log de HBase se trouve dans /var/log/hbase.
Sur notre machine Ubuntu, nous avons rencontr un problme avec le fichier hosts. Si vous
dmarrez le shell comme indiqu ci-aprs et que les commandes que vous lancez ne
rpondent pas, vrifiez votre fichier hosts. Supprimez la rfrence localhost sur la boucle
locale, indiquez la place le nom de la machine et ajoutez le nom hbase sur lIP de
linterface :
127.0.0.1 nom_de_la_machine

192.165.0.27 nom_de_la_machine hbase

Notez que sur Ubuntu, vous trouvez en gnral cette ligne :


127.0.1.1 nom_de_la_machine

Si cest le cas, supprimez-la, conservez uniquement 127.0.0.1, et relancez le dmon hbase-


master :

sudo service hbase-master restart

Le statut du master est visible dans une interface web, par dfaut sur le port 60010 (figure
5-7).
Figure 5-7
Linterface web de HBase

Mise en uvre
Nous allons voir comment mettre en uvre Hbase laide de linvite de commandes, et
avec du code client.

Utilisation du shell
Linvite de commandes HBase est un interprteur JRuby, qui comporte en plus des
commandes propres HBase. Pour le lancer, saisissez :
hbase shell

Les commandes supportes par le shell peuvent videmment tre obtenues via la
commande help. exit permet de le quitter.
Voyons dabord si tout est correct :
status

qui retourne :
1 servers, 0 dead, 0.0000 average load
La commande create permet de crer une table, laquelle on ajoute un dictionnaire de
dclarations de familles de colonnes avec loprateur lambda (la syntaxe de dfinition de
hachages en Ruby). Crons notre table darticles pour Passerelles :
create article, {NAME => auteur, VERSIONS => 3}, {NAME => contenu, VERSIONS =>
10}, {SPLITS => [1000, 2000, 3000, 4000]}

Cette commande cre une table nomme article, contenant deux familles de colonnes :
auteur et contenu. La famille de colonnes auteur conservera trois versions dans ses colonnes,
et contenu en gardera 10. La table est sharde manuellement sur les valeurs de cls 1000,
2000, 3000, 4000. Cette dernire indication est totalement optionnelle, elle permet de
spcifier des valeurs de partitionnement au lieu de laisser HBase dcider par lui-mme. Il
peut tre plus efficace de dcider du sharding manuellement, lavance, cela aide
prdfinir clairement votre systme.
Vrifions que la table existe :
list

qui retourne :
TABLE

article
1 row(s) in 0.0100 seconds

Insrons maintenant notre article :


put article, 1, auteur:prnom, Annie
put article, 1, auteur:nom, Brizard

put article, 1, auteur:e-mail, annie.brizard@cocomail.com


put article, 1, contenu:titre, pourquoi les lphants ont-ils de grandes
oreilles ?

Et rcuprons linformation :
get article, 1

Nous obtenons :
COLUMN CELL

auteur:e-mail timestamp=1353486681849, value=annie.brizard@cocomail.com


auteur:nom timestamp=1353486653844, value=Brizard

auteur:pr\xC3\xA9nom timestamp=1353486631132, value=Annie

contenu:titre timestamp=1353486716515, value=pourquoi les \xC3\xA9l\xC3\xA9phants


ont-ils de grandes oreilles ?

4 row(s) in 0.0400 seconds

Ajoutons une nouvelle version dune colonne :


put article, 1, contenu:titre, je reviens sur mon histoire doreilles

Et retrouvons toutes les versions de cette cellule :


get article, 1, {COLUMN => contenu:titre, VERSIONS => 2}

Nous obtenons :
COLUMN CELL

contenu:titre timestamp=1353487625448, value=je reviens sur mon histoire doreilles


contenu:titre timestamp=1353487561109, value=pourquoi les \xC3\xA9l\xC3\xA9phants

ont-ils de grandes oreilles ?


2 row(s) in 0.0090 seconds

Si nous voulons supprimer la ligne :


deleteall article, 1

nous pourrions tre tent dutiliser la commande delete, mais elle sert supprimer une
valeur de cellule et non une ligne. Pour supprimer la table, il faut la dsactiver au
pralable :
disable article

drop article

Programmation client
Il est plus facile daccder HBase partir de Java et des classes org.apache.hadoop. et
hbase.client. Laccs par un autre langage client est possible grce Thrift ou Avro. Nous
avons vu comment installer Thrift dans le chapitre 3 consacr aux choix techniques du
NoSQL. Voyons maintenant comment se connecter HBase.
Comme nous utilisons la distribution Cloudera, nous installons le serveur Thrift pour
HBase :
sudo apt-get install hbase-thrift

Nous gnrons dabord les classes Thrift partir de la dfinition du document HBase, que
nous rcuprons ladresse suivante : http://svn.apache.org/viewvc/hbase/trunk/hbase-
server/src/main/resources/org/apache/hadoop/hbase/thrift/Hbase.thrift.
wget https://svn.apache.org/repos/asf/hbase/trunk/hbase-server/src/main/resources/org/
apache/hadoop/hbase/thrift/Hbase.thrift

thrift --gen py Hbase.thrift

Nous excutons ensuite le script suivant :


#!/usr/bin/python

# coding=utf-8

import sys
sys.path.append(gen-py)

from thrift.transport.TSocket import TSocket

from thrift.transport.TTransport import TBufferedTransport


from thrift.protocol import TBinaryProtocol

from hbase import Hbase

transport = TBufferedTransport(TSocket(127.0.0.1, 9090))


transport.open()

protocol = TBinaryProtocol.TBinaryProtocol(transport)

client = Hbase.Client(protocol)
print client.getTableNames()

print client.getRow(article, 1)

Nous ajoutons au chemin des classes Python le rpertoire dans lequel ont t gnres les
classes Thrift pour HBase : sys.path.append(gen-py). Nous importons ces classes (hbase),
puis nous ouvrons un transport. Nous rcuprons ensuite le nom des tables prsentes sur le
serveur, ainsi que notre ligne darticles, avec la cl 1.
La documentation de lAPI Thrift est disponible cette adresse :
http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/thrift/doc-files/Hbase.html.
Un client Python est actuellement en dveloppement, il sagit de HappyBase
(https://github.com/wbolster/happybase) quil est dj possible dutiliser.
Interface REST
HBase offre galement une interface REST. Pour linstaller avec Coudera, utilisez la commande :
sudo apt-get install hbase-rest

Gestion des tables


Nous pouvons dclencher manuellement le compactage ou lajout dune partition en
utilisant linterface web dadministration, comme illustr sur la figure 5-8.

Figure 5-8
Outils de linterface web

Pour cela, il convient dutiliser les commandes compact et split du shell. Dautres
commandes sont disponibles pour manipuler les nuds du cluster, tapez help pour les
explorer :
help replication
6
Le Big Data Analytique

Depuis peu de temps, tout lenvironnement Hadoop a trs fortement volu. Les
limitations de lalgorithme MapReduce, principalement les lenteurs de fonctionnement et
lobligation de rester en mode batch, ont t progressivement leves. Le domaine de
lanalytique des grands volumes (le Big Data analytique) est devenu le sujet important du
moment, avec beaucoup dinnovations la cl rcemment. Aussi nous souhaitons dans ce
chapitre dresser un panorama des technologies actuelles du Big Data analytique, afin de
vous aider en comprendre les offres et les enjeux, et faire le choix parmi la plthore
doutils disponibles.

Prsentation
Nous avons parl dHadoop 2, nom de code YARN. Les nouveaux environnements de
traitement distribu qui voluent autour de YARN (ou ventuellement de son jeune
concurrent Mesos) permettent de rpondre deux dfis : lanalyse interactive et le
traitement de larges volumes de donnes en temps rel. Lanalyse interactive se ralise
maintenant laide de requtes SQL qui semblent traditionnelles mais qui vont dclencher
une analyse distribue sur un cluster large. Le traitement en temps rel seffectue laide
dalgorithmes de type DAG (Directed Acyclic Graph), de traitements de flux et
dalgorithmes de Machine Learning. Ces outils ont permis la naissance dun nouveau
poste informatique : celui de data analyst ou data scientist.
Dans ce chapitre, nous allons dabord prsenter une dmarche Big Data analytique
classique avec Sqoop et Hive, puis nous parlerons dun point de vue plus haut niveau des
solutions mergentes du Big Data analytique.

Sqoop et Hive
Nous avons dj suffisamment parl dinstallation. Ici, nous allons plus simplement
effectuer notre dmonstration avec la machine virtuelle de Cloudera, Cloudera quickstart
VM, dans laquelle toute la suite Cloudera communautaire (CDH) est prinstalle. Ce qui
nous intresse ce stade, cest de comprendre comment sont raliss en pratique
limportation et le requtage des donnes dans notre cluster Hadoop.
Nous tlchargeons donc la machine virtuelle sur http://www.cloudera.com/8. Nous
prenons pour notre part limage importable dans VirtualBox. Vous disposez galement
dune machine virtuelle VMWare. Il vous est aussi possible dessayer ces outils en ligne,
en choisissant sur le site de Cloudera, loption try Cloudera Live .
Nous importons limage de la machine virtuelle dans VirtualBox et nous dmarrons. Elle
est configure pour 4 Go de RAM. Si vous avez assez de mmoire sur votre machine hte,
augmentez cette valeur. Le systme dexploitation de la machine virtuelle est une
distribution CentOS (un Red Hat serveur communautaire) avec une interface graphique
gnome 2.
lheure o nous crivons, la version de CDH est la 5.3. Elle inclut une installation
dHDFS, Hadoop YARN, HBase et diffrents outils associs, notamment Apache Spark et
Impala.
Louverture de la machine virtuelle vous amne sur une page daccs aux fonctionnalits
incluses : http://quickstart.cloudera/. Nous allons, laide de CDH et de ces exemples,
faire un tour dhorizon des briques classiques dun systme de Big Data analytique.

Importer les donnes avec Apache Sqoop


Sqoop (http://sqoop.apache.org/) est loutil de facto pour changer des jeux de donnes
entre des bases relationnelles traditionnelles et un environnement Hadoop. Cest donc un
type doutil dETL (Extract Transform Load) comme on en a lhabitude dans le monde de
linformatique dcisionnelle. Les ETL traditionnels sont disponibles en modle
commercial : Informatica, Oracle Data Integrator ou SQL Server Integration Services,
pour en nommer quelques-uns. Des outils dETL libres existent galement, principalement
Talend et Pentaho Kettle9.
Sqoop, pour sa part, est spcialement conu pour les allers-retours entre une base
relationnelle et HDFS. Il supporte galement des moteurs NoSQL en destination : Hbase,
Accumulo et Cassandra. Hive, Hcatalog et Parquet sont aussi des destinations nativement
implmentes10.
Sa force est de sappuyer comme toutes les autres briques sur un modle distribu. Cest
un projet mature, top-level Apache depuis 2012, compltement redvelopp actuellement
dans une version Sqoop2 qui nest pas encore prte pour la production. La version stable
de production au moment o nous crivons ces lignes est la 1.4.5.
Sqoop est donc loutil de choix pour ce quon appelle en Hadoop le processus dingestion
(ingestion process), cest--dire la rcupration des donnes oprationnelles de production
pour nourrir le cluster analytique. Il peut ensuite assurer lexportation des fichiers rsultat
des batchs MapReduce (les fichiers doutput), ou toute autre analyse vers une base
relationnelle, MySQL par exemple, pour un traitement oprationnel ou laffichage aux
utilisateurs.
Limportation est ralise avec une connexion JDBC vers la source, et vers une destination
traditionnellement HDFS qui peut tre de format CSV, Avro binaire ou SequenceFile.
Limportation est effectue avec des threads qui sexcutent en parallle, dcoupant par
dfaut la table source en segments partir de sa cl primaire, et le rsultat consistera donc
en plusieurs fichiers sur HDFS.
Tables sans cl primaire
Si vous souhaitez importer une table sans cl primaire, ou dont la cl primaire est composite (compose de
plusieurs colonnes), vous devez utiliser loption split-by pour indiquer sur quelle colonne effectuer la
segmentation. Dans ce cas, vous devez donc importer une table la fois.

Sqoop rcupre les mtadonnes des tables quil importe et gnre au passage une classe
Java qui encapsule les mthodes daccs aux structures de donnes importes pour
MapReduce. Pour le dire autrement : Sqoop lit la structure des tables, importe les donnes,
et gnre du code Java (jar et source) avec les fonctions dinput et output pour
MapReduce. Vous pouvez le faire indpendamment de limport avec la commande sqoop
codegen.

Mais nous naurons pas besoin de cela pour notre petite dmonstration. Nous allons
importer les tables de la base dexemple de CDH et nous allons ensuite les utiliser pour
une requte dans Hive.
Lexemple dappel de Sqoop de Cloudera importe les tables en Avro. Nous allons tre plus
la pointe de lactualit en gnrant des donnes en Parquet, qui est maintenant une
destination nativement supporte par Sqoop. Nous ouvrons un terminal dans la machine
virtuelle CDH, et nous lanons la commande Sqoop suivante :
sqoop import-all-tables \
-m 5 \
--connect jdbc:mysql://quickstart.cloudera:3306/retail_db \

--username=retail_dba \
--password=cloudera \
--as-parquetfile \

--warehouse-dir=/user/hive/warehouse > import.log

Dans lordre : nous appelons Sqoop et nous lui demandons dexcuter la commande
import-all-tables, qui comme son nom lindique, importe toutes les tables de la base de
donnes que nous indiquons dans la chane de connexion JDBC qui suit dans loption --
connect. Pour importer une seule table, la commande sappelle simplement import. On peut
lui indiquer une table ou une requte SQL si on souhaite filtrer les donnes.
Voici un exemple dappel de Sqoop pour une table :
sqoop import-all-tables \

-m 5 \

--connect jdbc:mysql://quickstart.cloudera:3306/retail_db \
--table customers

Loption -m indique le nombre de mappers excuter simultanment. En fait, Sqoop utilise


Hadoop pour son importation. Il va gnrer des fonctions map pour limportation des
donnes et utiliser le cluster Hadoop pour excuter les tches dimportation. En
segmentant la source (le split), il peut donc sappuyer sur le cluster Hadoop pour importer
de larges volumes de donnes dune faon totalement distribue.
Tables volumineuses dans MySQL
Si vous dsirez importer des tables de grande taille depuis MySQL, mfiez-vous du pilote JDBC pour MySQL.
Celui-ci charge par dfaut toute la table en mmoire et va remplir le stack de votre JVM. Vous avez donc de fortes
chances de subir une erreur de type OutOfMemoryException. Utilisez la mthode setFetchSize() du pilote JDBC
pour changer ce comportement. Vous trouverez plus de dtails dans la documentation de MySQL :
http://dev.mysql.com/doc/connector-j/en/connector-j-reference-implementation-notes.html.
Nous indiquons enfin que nous voulons gnrer des tables Parquet, et quelles seront
situes dans le rpertoire /user/hive/warehouse dans HDFS.
Sqoop peut galement importer directement de Hive, en crant les informations de
mtadonnes des tables Hive dans son metastore. Cherchez la commande --hive-import dans
la documentation de Sqoop si vous souhaitez lutiliser.
Nous avons rsum la sortie affiche par la commande Sqoop pour ne conserver que les
dtails intressants de limportation dune des tables de la base MySQL.
sqoop.Sqoop: Running Sqoop version: 1.4.5-cdh5.3.0

manager.MySQLManager: Preparing to use a MySQL streaming resultset.

tool.CodeGenTool: Beginning code generation


manager.SqlManager: Executing SQL statement: SELECT t.* FROM categories AS t LIMIT 1

orm.CompilationManager: Writing jar file: /tmp/sqoop-cloudera/compile/0aa84631ee6e68f91

fb52ad6dd3b203e/categories.jar
mapreduce.ImportJobBase: Beginning import of categories

manager.SqlManager: Executing SQL statement: SELECT t.* FROM categories AS t LIMIT 1


mapreduce.JobSubmitter: number of splits:5
mapreduce.JobSubmitter: Submitting tokens for job: job_1425111945531_0007

impl.YarnClientImpl: Submitted application application_1425111945531_0007


mapreduce.Job: The url to track the job: http://quickstart.cloudera:8088/proxy/
application_1425111945531_0007/

mapreduce.Job: Running job: job_1425111945531_0007


mapreduce.Job: map 0% reduce 0%
mapreduce.Job: map 60% reduce 0%

mapreduce.Job: map 100% reduce 0%


mapreduce.Job: Job job_1425111945531_0007 completed successfully
mapreduce.Job: Counters: 30

File System Counters

FILE: Number of bytes written=660635


HDFS: Number of bytes read=31255

HDFS: Number of bytes written=10230

Job Counters
Launched map tasks=5

Other local map tasks=5

Total time spent by all map tasks (ms)=237299


Total megabyte-seconds taken by all map tasks=242994176

mapreduce.ImportJobBase: Transferred 9.9902 KB in 130.3421 seconds (78.4858 bytes/sec)

mapreduce.ImportJobBase: Retrieved 58 records.

Vous voyez que Sqoop fait un premier appel la table, avec loption LIMIT 1 du SELECT dans
MySQL, pour rcuprer les mtadonnes de la table. Ensuite, il construit un mapper quil
compile dans un fichier jar pour lenvoyer MapReduce. Le job MapReduce dmarre,
affiche son tat davancement puis ses statistiques dexcution la fin de son travail. Il ny
a ici quune phase map, limportation ne ncessite aucune agrgation via un reducer. la
fin, Sqoop retourne des informations de taux de transfert et de nombre de lignes affectes.
On peut vrifier que les donnes sont bien importes en affichant la liste des sous-
rpertoires de notre rpertoire de destination :
hadoop fs -ls /user/hive/warehouse

Mais on va le voir graphiquement avec Hue.


Si vous avez ralis limport et que vous souhaitez le recommencer, vous obtiendrez une
erreur. En effet, Sqoop ncrase pas par dfaut les donnes. Vous pouvez lui demander de
le faire laide de loption --delete-target-dir, ou vous pouvez supprimer le rpertoire au
pralable :
hadoop fs -rm -f -r /user/hive/warehouse

Si vous souhaitez raliser des importations incrmentales, vous pouvez importer dans des
rpertoires horodats si vous travaillez avec des fichiers plats, ou vous pouvez utiliser
loption --append pour demander Sqoop dajouter les donnes.
Voici quelques arguments intressants de limportation.
Tableau 6-1 Arguments de Sqoop

Argument Description
Ajoute un jeu de donnes dj existant en HDFS. Pour
--append les formats de fichiers, cre des nouveaux fichiers
incrmentiels avec un autre nom.
--as-avrodatafile Importe en Avro
--as-sequencefile Importe en SequenceFiles
--as-textfile Importe en fichiers texte (cest le format par dfaut)
--boundary-query <statement> Requte pour indiquer les segments de splits
--columns <col,col,col> Si prsent, nimporte que les colonnes mentionnes
--delete-target-dir Supprime le rpertoire de destination
--fetch-size <n> Nombre de lignes rcuprer en une fois
-m,--num-mappers <n> Nombre de tches de mapper excuter en parallle
-e,--query <statement> Importe le rsultat de la requte SELECT
Colonne sur laquelle effectuer le split. Par dfaut, la cl
--split-by <column-name>
primaire. Si la cl primaire est composite (place sur
plusieurs colonnes), vous devez indiquer cette option et
choisir une seule colonne.
--table <table-name> Nom de la table pour la commande import
--target-dir <dir> Destination HDFS pour les fichiers

--warehouse-dir <dir>
Destination HDFS pour le rpertoire parent de tables,
selon le format dimportation

--where <where clause>


Clause WHERE appliquer sur la source pour filtrer les
donnes importer
-z,--compress Active la compression en destination
Choix du codec de compression (le dfaut est gzip, les
--compression-codec <c> options correspondent aux codecs disponibles dans
Hadoop)

--null-string <null-string>
La chane crire en destination en cas de NULL dans la
cellule source.
La chane crire en destination en cas de NULL dans la
--null-non-string <null-string> cellule source, si elle nest pas de type string.

Importer les tables dans Hive


Apache Hive (https://hive.apache.org/) est une surcouche analytique Hadoop qui offre
une couche dabstration aux donnes HDFS sous forme dun modle tabulaire et
relationnel, et un langage de requte SQL nomm HiveQL, dont lobjectif est de
sapprocher du support de la norme SQL, et qui implmente entre autres des jointures. Le
travail de Hive, cest de transformer une requte HiveQL en un job MapReduce, de
lexcuter sur le cluster Hadoop et de rcuprer les rsultats sous forme de jeu de rsultat
tabulaire. Cest un projet n au sein de Facebook (la naissance officielle de Hive date
daot 2009, la publication dun white paper de lquipe Data Infrastructure de
Facebook). En fvrier 2015, le comit de gestion de projet Apache de Hive (la fondation
Apache dfinit des PMC Project Management Committee par projet, voir
http://www.apache.org/foundation/how-it-works.html) a vot la sortie de Hive 1.0, qui
correspond lancienne version 0.14.1. Cest un signe pour indiquer les progrs
importants effectus sur larchitecture de Hive, et le langage HiveQL.
Pour utiliser et requter les donnes avec Hive, vous devez les dclarer dans Hive comme
des tables, ce qui aura effet de les rendre manipulables, travers labstraction des donnes
que fournit Hive et qui sappelle le metastore. Le metastore est un service qui donne aux
clients les mtadonnes des tables dclares dans Hive et qui persiste ces mtadonnes
dans une base de donnes Apache Derby (Derby est un SGBDR libre dvelopp en Java
qui peut fonctionner comme client-serveur ou moteur embedded :
http://db.apache.org/derby/). Par dfaut, le metastore est local la machine Hive, mais
vous pouvez partager les mtadonnes entre machines en installant Derby en client-
serveur (https://cwiki.apache.org/confluence/display/Hive/HiveDerbyServerMode).
Pour dclarer nos tables dans le metastore, nous allons nous connecter au client interactif
Hive dans notre terminal, et lancer une commande CREATE TABLE.
hive

Nous allons importer seulement une table, customers, pour donner un exemple minimal. La
procdure pour limportation des autres tables coule de source, et plus forte raison si
vous utilisez la capacit de Sqoop dimporter directement dans Hive : le CREATE TABLE ci-
aprs ne sera plus pour vous que figure dexemple.
CREATE EXTERNAL TABLE customers (

customer_id int,

customer_fname varchar(45),
customer_lname varchar(45),

customer_email varchar(45),

customer_password varchar(45),
customer_street varchar(255),

customer_city varchar(45),

customer_state varchar(45),
customer_zipcode varchar(45)

)
STORED AS PARQUET

LOCATION hdfs:///user/hive/warehouse/customers;

Il faut lavouer, nous avons choisi ici la facilit : seulement des varchar. En effet, attention
aux types de donnes si vous voulez travailler avec Parquet et Hive. Le support de Parquet
pour Hive tant relativement rcent, tous les types de donnes de Hive ne sont par
reconnus dans le stockage Parquet pour Hive, qui sappelle PaquetSerDe (en Hive, un
SerDe est une interface de stockage : srialiseur, dsrialiseur).
La tche suivante vous donne un tat des lieux :
https://issues.apache.org/jira/browse/HIVE-6384. lheure o nous crivons ces lignes
(Hive 0.13), le type date nest support que sous forme de patch. Nous utilisons donc ici le
type timestamp.
Nous avons utilis la syntaxe STORED AS PARQUET qui est nouvelle en Hive 0.13, qui est la
premire version avoir un support natif de Parquet. Sur une version antrieure ( partir
de Hive 0.10), vous pouvez utiliser la syntaxe suivante :
CREATE EXTERNAL TABLE customers (


)
ROW FORMAT SERDE parquet.hive.serde.ParquetHiveSerDe

STORED AS INPUTFORMAT parquet.hive.DeprecatedParquetInputFormat


OUTPUTFORMAT parquet.hive.DeprecatedParquetOutputFormat
LOCATION hdfs:///user/hive/warehouse/customers;

Ne vous inquitez pas pour la mention Deprecated que vous pouvez lire dans les formats
dimport et dexport, les classes ont t nommes ainsi pour indiquer quelles utilisent le
vieil API org.apache.hadoop.mapred dans Hadoop, au lieu du plus rcent
org.apache.hadoop.mapreduce.

Aprs cration de la table, il nous suffit de vrifier que les donnes sont interrogeables :
select * from customers limit 1;

>OK

>9949 Ashley Smith XXXXXXXXX XXXXXXXXX 6631 Pleasant Zephyr Route


El Paso TX 79927

Time taken: 0.081 seconds, Fetched: 1 row(s)

Pour une simple requte comme celle-ci, Hive na pas besoin de crer un job MapReduce.
Il choisira de le faire si nous lui demandons quelque chose de plus compliqu.

Grer les donnes avec Apache Hue


Hue (http://gethue.com/) est labrviation de Hadoop User Experience. Cest une interface
web qui donne accs aux donnes stockes dans HDFS. Sur CDH, Hue est configur pour
rpondre sur le port 8888. Il centralise laccs aux informations de HDFS, Hive et Impala.
Hue vous permet de visualiser simplement larborescence HDFS (figure 6-1) et le
metastore de Hive (figure 6-2).
Figure 6-1
Arborescence HDFS dans Hue

Figure 6-2
Hive metastore dans Hue

Nous allons utiliser Hue pour saisir une requte Hive comportant un filtre dans la clause
WHERE, et observer comment lexcution est mene.

Nous allons sur lditeur de requte (Query Editor) et nous crons une nouvelle requte
Hive (figure 6-3).

Figure 6-3
Editeur de requte Hive dans Hue
Notre requte :
SELECT c.customer_fname + + c.customer_lname as custname
FROM customers c

WHERE c.customer_fname LIKE A%


AND c.customer_lname = Smith

ORDER BY custname;

est une pure requte SQL utilisant une syntaxe dfinie dans la norme SQL-92, notamment
pour lutilisation du LIKE dans la clause WHERE, et la dfinition des alias. Il y a naturellement
quelques spcificits Hive. Vous voyez par exemple que nous rutilisons lalias dfini
dans le SELECT comme critre de tri dans lORDER BY. Cest bien sr parfaitement valide, car
dans lordre dexcution logique dun ordre SQL, lORDER BY svalue aprs le SELECT et peut
rutiliser les alias dfinis auparavant. Mais dans un SGBDR, lORDER BY peut aussi contenir
des critres qui ne sont pas exprims dans le SELECT : cest ce quon appelle un critre
externe. Dans HiveQL, ce nest pas possible : vous devez indiquer une colonne ou un alias
tel quil est prsent dans le SELECT.
Support de la norme SQL
Nous lavons dit, lobjectif de HiveQL est le support complet de la norme SQL, spcifiquement SQL-92, et dans
lidal SQL-2011. Hive inclut notamment tous les types de jointures (internes, externes et croises) mais seulement
en quijointures (comparaison avec galit), sous-requtes, fonctions de fentrage (windowing functions) et
fonctions utilisateurs (UDF : user defined functions) crites en Java.

Lexcution de cette requte va entraner la cration dune fonction de mapper qui sera
excute par MapReduce. Hue affiche un log en temps rel (figure 6-4) et donne un lien
sur le job MapReduce en excution.

Figure 6-4
Journal dexcution du job MapReduce

Le lien nous envoie sur le job browser, qui affiche galement un journal des jobs excuts
et termins (figure 6-5).
Figure 6-5
Job log dans Hue
Stinger
Hortonworks et dautres acteurs ont lanc linitiative Stinger (http://hortonworks.com/labs/stinger/) dont lobjectif
est de rendre Hive pratiquement interactif en temps rel, dy ajouter la possibilit de modifier les donnes avec une
garantie ACID de la transaction, un moteur dexcution qui vectorise le traitement (nous avons parl des vecteurs
dans notre section sur le format ORC File, page 123), des non-quijointures et des vues matrialises.

Apache Spark
Les intiatives, les projets, les frameworks autour du Big Data analytique poussent en ce
moment comme des champignons. Pour clore ce chapitre, nous allons voquer un projet
important nomm Spark.
Apache Spark est lun des projets du Big Data analytique les plus intressants. Il est
constitu de plusieurs couches trs bien intgres qui offrent tout ce dont vous avez besoin
pour dans un environnement de Big data complet. lheure o nous rdigeons cet
ouvrage, la dernire version est la 1.2.1, sortie en fvrier 2015. Spark a t dvelopp
lorigine par luniversit de Californie Berkeley, puis transmis la fondation Apache. Il
est maintenant dvelopp par environ 500 contributeurs, ce qui en fait le projet le plus
actif de la fondation.
Spark (https://spark.apache.org/) est un environnement complet de stockage et de
traitement distribu. Pendant quelques annes, faire du Big Data analytique signifiait
installer diffrentes couches, par exemple HDFS, HBase et Hadoop, ensuite Hive pour les
requtes. Le but de Spark est de fournir tout ce qui vous est utile dans le mme outil,
lequel prend en charge lintgration de tous les modules ncessaires.
Il existe un autre environnement de ce type appartenant galement la fondation Apache,
nomm Apache Tez. Cest une implmentation concurrente de Spark, elle aussi libre, dont
lquipe est issue de plusieurs entreprises. Mais la plupart des contributeurs proviennent
dune socit spcialise dans la distribution et le support de solutions Hadoop :
Hortonworks. Spark en revanche est principalement distribu par Cloudera. On peut donc
y voir deux produits concurrents des deux plus importantes entreprises du monde Hadoop.
Dans les faits, lheure actuelle, Spark est un projet plus mature, plus actif et plus riche
que Tez. Une socit a t fonde par les dveloppeurs de Spark, nomme Databricks
(https://databricks.com/), qui offre un environnement cloud autour de Spark, ainsi que des
formations et un processus de certification.

Caractristiques
Avant de prsenter larchitecture de Spark, prcisons dj quelque chose dintressant : il
est trs rapide. Ctait lun des objectifs de son dveloppement : corriger les lenteurs
dHadoop qui sont dues son architecture, et notamment au fait que limplmentation
dHadoop MapReduce travaillait directement avec les fichiers sur le disque en HDFS.
Rien nest prvu dans MapReduce pour maintenir un cache en mmoire. Spark au
contraire va charger les donnes en mmoire vive de faon pouvoir optimiser de
multiples traitements. Il est typiquement de 10 100 fois plus rapide que Hadoop
MapReduce. Il existe un concours annuel de performances des environnements de Big
Data, que vous trouvez ladresse http://sortbenchmark.org/. Le but est de trier le plus
rapidement possible un jeu de donnes dun volume de 100 To. Il y a plusieurs mtriques
et plusieurs jeux de donnes, dont vous trouvez les rfrences sur le site, mais simplifions
ici et conservons la mtrique la plus importante sur le premier jeu de donnes utilis. En
2013, le gagnant tait un cluster Hadoop de Yahoo! qui est parvenu trier 102.5 To en 4
328 secondes, sur un cluster de 2 100 nuds de machines avec 64 Go de mmoire. Cela
fait un rythme de tri de 1,42 To la minute.
En 2014, il y a deux gagnants ex aequo : un systme nomm TritonSort dvelopp par
luniversit de Californie San Diego, et Spark. Spark a tri 100 To en 1 406 secondes sur
un cluster Amazon ec2 de 207 noeuds de 244 Go de mmoire et disque SSD. Le test a t
ralis par Databricks. Cela quivaut un rythme de 4,27 To par minute, cest--dire trois
fois mieux quHadoop avec 10 fois moins de machines (mais beaucoup plus de mmoire
vive). Grce des environnements comme Spark, le Big Data analytique est en train de
raliser peu peu la promesse dun traitement volumineux en temps rel.

Architecture
Le cur de Spark est un module nomm Spark Core. Il offre les fonctionnalits de base,
savoir la distribution et la planification des tches, ainsi que les primitives dentres-
sorties. Spark Core utilise pour ses entres-sorties une abstraction nomme RDD, pour
Resilient Distributed Datasets (jeux de donnes distribus rsilients). Le nom voque le
fait que les donnes sont naturellement distribues, et rpliques de faon pouvoir
survivre aux dfaillances matrielles des nuds. Cette abstraction permet Spark Core de
travailler de manire identique avec nimporte quel stockage physique sous-jacent. Cette
couche offre donc un niveau intermdiaire qui permet dallier au niveau bas nimporte
quel type de stockage et diffrents environnements de distribution des tches comme
Hadoop YARN ou Mesos, et au niveau haut, plusieurs algorithmes ou environnements de
traitement qui se basent sur Core pour laccs la planification et aux donnes. Sont
actuellement disponibles avec Spark quatre formes de traitement : des moteurs
dexcution SQL pour le requtage interactif, le module Spark Streaming pour le
traitement en temps rel des flux, MLib pour les algorithmes dapprentissage sur les
donnes (le Machine Learning) et le module GraphX pour le traitement des graphes
distribus.
Figure 6-6
Architecture de Spark

8. Nous vitons ici dcrire lURL complte, dans la mesure o elle a tendance changer lorsque Cloudera met jour
son site. Cherchez simplement CDH (qui est peu prs labrviation de Cloudera Distribution of Hadoop) dans les
produits sur le site.
9. Dailleurs, Talend, une socit franaise, propose un environnement Hadoop li leur outil dETL graphique ; le tout
est nomm Talend Open Studio for Big Data (http://www.talend.com/get/bigdata).
10. Le support de Parquet notamment a t ralis en septembre 2014 via un dveloppement conjoint dIntel et de
Cloudera, voir http://ingest.tips/2014/11/10/parquet-support-arriving-in-sqoop/.
7
CouchDB et Couchbase Server

CouchDB est un systme de gestion de bases de donnes destin principalement aux


applications web, en raison de son support des protocoles propres au Web. Les documents
au format JSON sont manipulables en JavaScript travers une interface HTTP.
CouchDB offre une grande richesse fonctionnelle au niveau du serveur, avec la possibilit
de dfinir des filtres et des vues dans le langage de votre choix habituellement
JavaScript avec un support de MapReduce, et qui gnre des index pour offrir de
meilleures performances.
Cela dit, CouchDB souffre de plusieurs dfauts qui le rendent peu apte soutenir des
applications de production exigeantes. En revanche, Couchbase Server, qui est une
volution de Membase et de CouchDB, est plus adapt aux besoins de production. Nous
allons tudier ces deux moteurs dans ce chapitre.

Prsentation de CouchDB
CouchDB a t cr par Damien Katz, un ancien dveloppeur de Lotus Notes chez IBM. Il
le dveloppa pendant deux ans, avant de le librer sous Licence Apache. Son but tait de
faire de CouchDB un moteur de bases de donnes adapt Internet. En 2011, Damien
Katz a annonc quil allait se concentrer sur le dveloppement de CouchBase Server, en
intgrant la socit Couchbase. Il en fut le Chief Technical Officer jusquen aot 2013.

Caractristiques
CouchDB est dvelopp en Erlang, un langage fonctionnel particulirement adapt
linformatique distribue et cr par la socit Ericsson (Erlang est une contraction de
Ericsson Language). Ce langage comporte nativement des fonctionnalits de distribution
des processus. CouchDB est un moteur de bases de donnes orient documents, ce qui
signifie quil stocke et manipule des structures JSON (comme MongoDB que nous
tudierons au chapitre 8). Son objectif est dtre simple et intuitif utiliser (do son nom
relaxant de CouchDB), mais aussi adapt pour le Web. ce titre, il offre au programmeur
une interface REST qui le rend accessible de partout et avec nimporte quel langage, une
gestion de la monte en charge aussi automatique que possible, et des fonctionnalits
natives de gestion des donnes distribues. Souvenons-nous de ces informations : Erlang,
JSON, REST. Nous en retrouverons lhritage dans Couchbase Server.
La cohrence des donnes est assure par une gestion de versions de type MVCC
(Multiversion Concurrency Control), cest--dire un verrouillage optimiste qui ne bloque
pas la donne sur le serveur lorsquelle est en modification chez un client, mais qui
sassure au moment de la mise jour quelle na pas t modifie sur le serveur entre-
temps.
Les vues permettent, travers des fonctions procdurales qui sappliquent aux donnes et
une implmentation transparente et purement locale de lalgorithme MapReduce,
deffectuer des recherches sur des documents dont la structure nest pas homogne laide
de fonctions map et reduce. Les vues permettent donc de travailler lgamment sur des
donnes sans schma prdfini.

Mise en uvre de CouchDB

Installation
Les fichiers dinstallation de CouchDB peuvent tre tlchargs sur le site qui lui est
ddi : http://couchdb.apache.org/. lheure o nous crivons ces lignes, la dernire
version stable est la 1.6.1. Une version 2 est en dveloppement. CouchDB est disponible
dans les dpts Debian/Ubuntu, en gnral avec au moins une version de retard. Les
moteurs NoSQL voluant vite, nous vitons en gnral dinstaller danciennes versions.
En dautres termes, vous lavez compris, nous allons effectuer une installation manuelle,
ou plutt semi-manuelle, car un outil est tout de mme disponible pour nous simplifier le
travail. En effet, nous allons utiliser le script build-couchdb, crit en Ruby et disponible
ladresse suivante sur le site Github : https://github.com/iriscouch/build-couchdb.
Compilation de CouchDB
Si vous souhaitez compiler CouchDB de faon entirement manuelle, consultez la marche suivre indique sur la
page suivante : http://wiki.apache.org/couchdb/Installing_on_Ubuntu.

La premire chose faire est dinstaller quelques dpendances ncessaires au script build-
couchdb et CouchDB.

sudo apt-get install help2man make gcc zlib1g-dev libssl-dev rake help2man git

Nous tlchargeons ensuite build-couchdb depuis Github.


cd ~/downloads

git clone git://github.com/iriscouch/build-

cd build-couchdb

git submodule init


git submodule update

La commande git submodule permet de tlcharger automatiquement les dpendances


ncessaires pour compiler CouchDB. Lorsque le tlchargement est termin, il suffit de
lancer rake, loutil de make de Ruby. rake va inscrire le chemin de destination de la
compilation un peu partout dans les scripts de lancement de CouchDB. Pour placer
CouchDB compil directement au bon endroit, nous indiquons rake le rpertoire
dinstallation. Nous lanons la commande en sudo, de manire donner les droits
ncessaires lutilisateur courant sur notre rpertoire de destination, savoir /usr/local/.
sudo rake install=/usr/local/couchdb

rake va excuter le rakefile livr avec build-couchdb, tlcharger les dpendances ncessaires
CouchDB et le compiler. Cela peut prendre un certain temps. Vous trouverez ensuite le
rsultat de la compilation dans le rpertoire build/. Vrifions dabord que CouchDB est
bien compil et que nous avons la dernire version :
/usr/local/couchdb/bin/couchdb -V

Nous obtenons :
couchdb - Apache CouchDB 1.6.1

et la mention de la licence. Tout va bien.


Afin dviter dexcuter CouchDB en tant que root, nous crons un utilisateur nomm
couchdb et nous lui donnons les droits sur le rpertoire de CouchDB compil.

sudo adduser couchdb

sudo chown -R couchdb /usr/local/couchdb

Nous lanons ensuite CouchDB :


su couchdb
nohup /usr/local/couchdb/bin/couchdb &

nohup et & permettent de lancer le processus en tche de fond et de le laisser actif mme si
lutilisateur ferme sa session.
Nous pouvons maintenant vrifier si CouchDB est lanc, par exemple en trouvant son
processus, ou en contrlant sil coute sur son port par dfaut, le port TCP 5984 :
ps -aux | grep couchdb

netstat -lt

La commande ps retourne la liste des processus, et nous filtrons avec grep. La commande
netstat -lt affiche les connexions rseaux ouvertes en coute (-l) en protocole TCP/IP (-t).
Le rsultat est prsent sur la figure 7-1.

Figure 7-1
Rsultat de netstat : coute en local

CouchDB est bien lanc et coute bien sur le port 5984. En revanche, on peut voir quil
coute seulement sur la boucle locale (localhost). Nous remarquons aussi, dans le rsultat
de la premire commande, que les fichiers de configuration dfinis se trouvent aux
emplacements /usr/local/couchdb/etc/couchdb/default.ini et
/usr/local/couchdb/etc/couchdb/local.ini. Default.ini contient la configuration de CouchDB,
mais vous ne devriez pas modifier ce fichier, car il sera cras lors dune mise jour et
tous les changements seront alors perdus. Utilisez plutt le fichier local.ini, qui ne sera pas
remplac en cas de mise jour et dont les paramtres ont priorit sur ceux de default.ini
(puisquil est list en second dans les listes des fichiers de configuration de CouchDB).
Cest donc dans local.ini que nous allons modifier la configuration de la faon suivante :
[httpd]
bind_address = 0.0.0.0

Ensuite, nous tuons CouchDB et nous relanons le processus :


ps -U couchdb -o pid= | sudo xargs kill -9

su couchdb
nohup /usr/local/couchdb/bin/couchdb &

La figure 7-2 montre le nouveau rsultat du netstat.

Figure 7-2
Rsultat de netstat : coute sur toutes les interfaces

Nous pouvons ensuite tester linterface de CouchDB laide dun client web ou de
lutilitaire en ligne de commandes curl. Sur la machine o CouchDB est install, cet
appel :
curl http://localhost:5984/

retourne un simple document :


{couchdb:Welcome,version:1.6.1}

Utilisation de Futon
Futon est loutil web de gestion de CouchDB. Pour le trouver, appelez le chemin _utils de
lemplacement web de CouchDB. La figure 7-3 reprsente la page daccueil du site de
Futon appele sur notre serveur http://nosql-server:5984/165_utils/.
Figure 7-3
Futon

Pour vous assurer que votre installation de CouchDB est totalement fonctionnelle, rendez-
vous dans le menu Tools et cliquez sur Verify Installation qui permet une validation
simple. Vous pouvez galement utiliser les scripts JavaScript de test livrs par Futon dans
le menu For Developers: Test Suite. Lancez le test Basic.
Nous pouvons maintenant essayer de crer une base de donnes laide de Futon. Nous
crons dabord la base de donnes en cliquant sur le lien Create Database situ en haut
gauche dans laffichage de vue densemble de Futon. Nous la nommons passerelles, tout en
minuscules, car une base de donnes CouchDB ne peut pas contenir de majuscules. Nous
sommes ensuite dirigs vers la base de donnes dans laquelle nous pouvons ajouter des
documents, laide du lien New Document. Nous voulons ajouter notre entre de blog
pour notre site Passerelles. Linterface de Futon nous propose dajouter le document
champ par champ.

Utilisation de lAPI REST


Voici quelques exemples dappel CouchDB laide de curl (pour plus dinformations sur
curl, voir la section curl du chapitre 3, page 67). La commande suivante cre la base de
donnes passerelles.
curl -X PUT http://localhost:5984/passerelles
Nous insrons ensuite un petit document dans la base :
curl -X PUT http://localhost:5984/passerelles/1 -d
{

auteur:
{

prnom:Annie,
nom:Brizard,

e-mail:annie.brizard@cocomail.com

},
titre:pourquoi les lphants ont-ils de grandes oreilles ?

et nous le retrouvons :
curl -X GET http://localhost:5984/passerelles/1

Le rsultat est illustr sur la figure 7-4.

Figure 7-4
Appel REST avec curl

Afin de grer la consistance des modifications de donnes, CouchDB maintient les


rvisions successives des mises jour sur un document. Nous pouvons voir sur la figure 6-
4 lidentifiant de rvision dans la cl _rev. On peut effectuer une modification du document
en refaisant un PUT sur la mme URL de document et en indiquant le numro de la dernire
rvision :
curl -X PUT http://localhost:5984/passerelles/1 -d

_rev: 1-dc5def75ffe9db45c5c3de4d21ebabb8,
auteur:

prnom:Annie,
nom:Brizard,

e-mail:annie.brizard@cocomail.com

},
titre:je change mon titre, il tait trop bizarre

Ce qui retourne un nouveau numro de rvision :


{ok:true,id:1,rev:2-1a97e3eb387fd93cf6e1abb2a1aed56b}

Numro de rvision
Le numro de rvision est un hash en MD5 de la modification, prcd dun numro indiquant le nombre de fois o
le document a t mis jour.
Nous avons vu dans le chapitre 3 page 89 que lobligation denvoyer un numro de
rvision permet de grer un mode de verrouillage optimiste.
Si vous oubliez le numro de rvision, ou si vous indiquez autre chose que le dernier
numro de rvision, vous obtiendrez lerreur suivante :
{error:conflict,reason:Document update conflict.}

Prenons exemple sur la suite dappels suivante, o sont indiques les rponses de
CouchDB :

Nous avons essay denvoyer deux fois un document avec le mme numro de rvision.
La seconde fois, nous avons obtenu une erreur : le numro de rvision ntait plus le
numro actuel, il y a donc eu un conflit.
LAPI de CouchDB est riche en fonctionnalits. Pour vous donner un exemple, suivons
notre trace de rvisions. Afin dobtenir plus dinformations sur les rvisions de notre
document, nous demandons dajouter dans le document en retour le champ spcial
_revs_info :

Ce qui retourne le rsultat suivant :


Nous aurions aussi pu demander la liste des numros de rvision du document sans plus de
dtail :
curl -X GET http://localhost:5984/passerelles/1?revs=true

Nous aurions alors obtenu le rsultat suivant :


_revisions:{start:2,ids:[1a97e3eb387fd93cf6e1abb2a1aed56b,dc5def75ffe9db45c5c
3de4d21ebabb8]}

Vous avez peut-tre not que les id de rvision diffrent entre les deux appels. Ceci vient
du fait que _revs_info agrge un numro de rvision avec lID de rvision, de faon
afficher une squence.
Nous pouvons ensuite requter une rvision particulire, par exemple :

qui retournera le titre pourquoi les lphants ont-ils de grandes oreilles ?


Vous pouvez obtenir toutes les rvisions ou certaines rvisions dun document avec les
syntaxes suivantes :

et _rev sont des champs particuliers.


_id

Utilisation de lAPI REST dans le code client


Dans la prochaine section, nous allons dcouvrir quelques fonctionnalits du serveur
CouchDB. Mais avant cela, nous devons crer une base CouchDB avec un peu de matire.
laide dun script Python, nous allons prendre un flux RSS et stocker les articles de ce
flux dans une base de donnes CouchDB. Avant de crer le code, nous devons importer
deux bibliothques dans notre environnement Python : feedparser, pour manipuler le flux
RSS, et requests, pour appeler simplement lAPI REST depuis notre code.
~/python_env/nosql/bin/pip install feedparser

~/python_env/nosql/bin/pip install requests

Nous allons convertir les articles de flux en documents JSON. Nous rencontrons ici un
problme, car la bibliothque feedparser retourne certains lments du flux dans des types
de donnes incompatibles avec JSON, notamment la date de larticle qui est de type
Python time.asctime. Pour rsoudre ce problme, nous crons un module nomm
customserializer.py que nous plaons dans le mme rpertoire que le script que nous allons
crer. Ce module sera utilis par la mthode dumps de la bibliothque json pour prendre en
charge les types qui posent problme. Nous avons rcupr le code suivant du livre Dive
Into Python 3, disponible en ligne ladresse suivante :
http://getpython3.com/diveintopython3/serializing.html.
Ensuite, nous pouvons crer notre script, dont le code est le suivant :
#!/usr/bin/python
# coding=utf-8
import json

import requests
import customserializer
from feedparser import parse

url = http://127.0.0.1:5984/actualitte
i = 1
# on supprime la base au cas o

print requests.delete(url)
# on la cre
print requests.put(url)

from feedparser import parse


myfeed = parse(http://www.actualitte.com/flux-rss-news.xml)
print myfeed.feed.title

for item in myfeed.entries:

j = json.dumps(item, default=customserializer.to_json)
cle = %05d % i

print requests.put(url+/+cle, data=j)

i += 1

Aprs avoir import les modules ncessaires, nous dfinissons notre URL REST
http://127.0.0.1:5984/actualitte. actualitte correspond au nom du site dont nous rcuprons le
flux, nous en faisons donc le nom de notre base de donnes.
ActuaLitt
Le site ActuaLitt (http://www.actualitte.com/) est un portail ddi lactualit littraire. Nous lavons choisi
simplement parce que son flux RSS est trs rgulirement mis jour.

Nous utilisons le module requests pour nos appels REST : requests.delete(url) nous permet
de supprimer la base de donnes si elle existe dj afin de recommencer notre test depuis
le dbut (sans base donc). Nous effectuons ensuite un PUT pour (re)crer la base. laide
de feedparser, nous rcuprons le flux et nous bouclons lintrieur des articles. Pour
chaque article, nous utilisons la mthode json.dumps pour convertir lobjet Python en une
structure JSON, en passant par notre customserializer pour grer les types incompatibles.
Nous prenons soin galement de gnrer une cl pour chaque entre, avec un compteur
incrment dans la boucle et que nous formatons sur cinq positions (par exemple 00001).
Comme le stockage en B-Tree de CouchDB est ralis dans lordre alphabtique des cls,
nous nous assurons ainsi de bien insrer nos articles dans lordre, principalement pour
rendre les rsultats de notre exemple bien lisibles. Enfin, nous lanons un PUT laide de
requests.put en passant notre JSON en paramtre data (la documentation sur le
fonctionnement de requests.put est disponible cette adresse : http://docs.python-
requests.org/en/latest/api/?highlight=put#requests.put).
Nous nommons notre script get_actualitte.py et nous lexcutons :
~/python_env/nosql/bin/python get_actualitte.py

Nous obtenons une suite de rponses gnres par le print de notre requests.put :
<Response [201]>

Dans Futon, nous trouvons bien notre base de donnes, qui contient une suite darticles.
La figure 7-5 reprsente un morceau darticle tel que visualis dans Futon.

Figure 7-5
Article visualis dans Futon

Enfin, si nous accdons notre base de donnes via linterface REST, nous obtenons un
tat de la base travers un retour structur en JSON. Il nous suffit de saisir le code
suivant :
curl http://127.0.0.1:5984/actualitte

qui retourne :
{db_name:actualitte,doc_count:30,doc_del_count:0,update_seq:30,purge_
seq:0,compact_running:false,disk_size:122984,data_size:90615,instance_start_

time:1347615883371079,disk_format_version:6,committed_update_seq:30}

Notre base contient trente documents.

Fonctionnalits du serveur
Cration et utilisation des vues
Maintenant que nous avons aliment une base avec quelques documents, voyons comment
utiliser les vues pour effectuer des recherches, ce que nous allons faire directement dans
Futon. Pour cela, nous revenons laffichage de la base de donnes
(http://127.0.0.1:5984/171_utils/database.html ?actualitte sur notre machine locale) et dans
la liste droulante View, nous slectionnons Temporary view (figure 7-6).

Figure 7-6
Cration dune vue temporaire

Nous devons utiliser JavaScript, ou ventuellement CoffeeScript, un surlangage qui


gnre du JavaScript et dont la syntaxe est influence par les langages de script comme
Python et surtout Ruby. Une vue implmente les deux fonctions de MapReduce : la
fonction Map est applique chaque document, et la fonction Reduce, optionnelle, peut tre
utilise pour retourner une agrgation.
Notre premire vue sera vraiment trs simple. Notre fonction Map sera la suivante :
function(doc) {
if (doc.published) {

emit(doc.published, doc);

}
}

Nous allons simplement retourner nos documents organiss selon une nouvelle cl, qui
correspond la date de publication (doc.published).
Test dexistence de la cl
Dans notre fonction, nous testons lexistence de la cl published avant de retourner le document. Cest un lment
important des vues dans CouchDB, car si la cl nest pas prsente dans tous les documents, les erreurs provoques
par le rsultat de la fonction risquent de forcer CouchDB dsactiver lindexation du rsultat. En testant lexistence
de la cl, nous nous assurons de ne retourner que les documents qui ont la structure qui nous intresse. Cest une
manire lgante de prendre en compte des documents de structures diffrentes dans la mme base de donnes.

La seule fonction que nous appelons dans ce code trs simple est emit(). Elle quivaut au
return dune fonction ( la diffrence quemit() peut tre appele plusieurs fois si vous
voulez retourner plusieurs documents partir dune seule itration de la boucle map) et
permet laffichage dun document en retour de la fonction. Les deux paramtres demit()
correspondent la structure dun document : dabord la cl, puis le document lui-mme.
Le rle de la partie map dune vue consiste rcuprer la liste des documents retourne par
les excutions demit() et restituer cette liste ordonne par la cl, donc la valeur du
premier paramtre demit().
Comme cette vue est temporaire, son rsultat est dynamique, cest--dire que lapplication
de la fonction map est ralise lappel de la vue pour tous les documents de la base de
donnes. Elle sera donc assez lente excuter. Les vraies vues, non temporaires, sont des
vues matrialises : lors de leur premier appel, elles stockent le rsultat de la fonction map
dans un B-Tree, de faon permanente sur le disque, et les modifications de donnes y sont
conserves en temps rel lors des ajouts et mises jour des documents. En dautres
termes, les vues ressemblent trs fortement aux vues matrialises des SGBDR. Pour crer
ces vues durables, nous allons utiliser des documents de conception (design documents).
La vue peut trs simplement faire office dindex secondaire. Voyons une transformation de
notre vue temporaire :
function(doc) {

if (doc.published) {
emit(doc.published, null);

}
}

La seule diffrence est que nous avons retir le second argument de la fonction emit(), nous
renvoyons un null. En excutant la fonction, nous obtenons le rsultat illustr sur la figure
7-7.
Figure 7-7
Rsultat de la vue

La partie Value du rsultat ne contient rien, mais dans la partie Key, nous avons la cl
dfinie dans notre fonction ainsi que lID du document dorigine. LID est
automatiquement ajout dans le rsultat dune vue afin de faire rfrence ce document,
ce qui correspond lusage dun index secondaire.

Design documents
Les design documents constituent lun des lments les plus intressants de CouchDB. Ils
reprsentent une forme lgante de traitement des donnes au niveau du serveur, en offrant
des fonctionnalits semblables ce quon trouve dans un moteur SQL : vues, procdures
stockes, dclencheurs et contraintes.
Nous modifions la vue temporaire que nous avons cre dans Futon, en inscrivant ceci
dans la fonction map :
function(doc) {
if (doc.tags.length > 0) {

for(var i in doc.tags) {

emit([doc.tags[i].term, doc.author_detail.name], 1);


}

Vous voyez dans cette modification de la fonction que nous pouvons manipuler des listes
du document. Nous bouclons ici dans la collection de tags (les mots-cls) de chaque article
et nous effectuons un emit() pour chaque terme trouv. Le rsultat de la fonction peut donc
potentiellement retourner plus de paires cl-valeur que le nombre de documents originels.
Nous voyons galement que la cl que nous dfinissons dans la fonction emit() peut elle-
mme tre compose dune liste. Ensuite, nous ajoutons ceci dans la partie reduce :
function(keys, values, rereduce) {

return sum(values)
}

Puis nous utilisons le bouton Save As pour sauvegarder notre vue dans un design
document (figure 7-8).

Figure 7-8
Sauvegarde de la vue

Une bote de dialogue souvre pour nous permettre de choisir le nom de notre design
document et le nom de la vue qui y sera cre. Un design document peut contenir
plusieurs vues, et il sera toujours prfix par _design/, considrez cela comme une forme
despace de noms. Le document cr sera un vrai document dans le sens de CouchDB et il
contiendra du JSON. Lavantage de ceci est quil sera possible de le traiter comme les
autres documents, dans toutes les oprations comme les mises jour ou la rplication.
Pour notre exemple, nous nommons le document _design/vues_exemple et la vue qui sy
trouve par_tags_et_auteur.
Nous pouvons maintenant utiliser la vue dans Futon. Nous revenons au niveau de la base
de donnes actualitte et nous choisissons dans le menu droulant View la vue
vues_exemple/par_tags_et_auteur. Nous cliquons sur la case cocher Reduce. Une liste
droulante nous permet alors de choisir le regroupement, nous slectionnons level 1. Le
rsultat est illustr sur la figure 7-9.
Figure 7-9
Appel de la vue dans Futon

La fonction map nous a retourn une liste de cls bases sur un tag, puis le nom de lauteur
de larticle. En valeur, nous retournons simplement 1 afin de pouvoir en faire la somme
dans la fonction Reduce. Lorsque nous appelons la vue, nous pouvons choisir ou non
dappliquer la fonction Reduce, et quel niveau de regroupement. Nous avons effectu un
agrgat de nos donnes, comme si nous avions crit une requte SQL avec une clause GROUP
BY.

Voyons enfin comment appeler cette vue depuis linterface REST. Lappel de la vue se fait
ladresse base_de donnes/_design/nom_du_design_document/_view/nom_de_la_vue.
curl

http://192.168.0.14:5984/actualitte/_design/vues_exemple/_view/par_tags_et_auteur

qui retourne ceci :


{rows:[

{key:null,value:30}

]}

Il sagit donc de lapplication de la fonction Reduce avec un niveau de regroupement total,


ce qui quivaut :
curl http://192.168.0.14:5984/actualitte/_design/vues_exemple/_view/
par_tags_et_auteur?group_level=0

Descendons ensuite dans les niveaux :


curl http://192.168.0.14:5984/actualitte/_design/vues_exemple/_view/

par_tags_et_auteur?group_level=1
ce qui retourne :
{rows:[
{key:[Acteurs numriques],value:2},

{key:[Bibliothques],value:4},
{key:[Comics],value:1},

{key:[Expositions],value:1},
{key:[Insolite],value:1},

{key:[International],value:6},

{key:[Justice],value:1},
{key:[Lgislation],value:1},

{key:[Les maisons],value:3},

{key:[Librairies],value:2},
{key:[Rcompenses],value:1},

{key:[Scolarit France],value:1},
{key:[Socit],value:1},
{key:[Univers BD],value:1},

{key:[Usages],value:4}
]}

Enfin, compliquons un peu notre dernier exemple :


curl --globoff http://192.168.0.14:5984/actualitte/_design/vues_exemple/_view/par_
tags_et_auteur?startkey=[I]&endkey=[J]&limit=3&group_level=2

ce qui retourne :
{rows:[

{key:[Insolite,Julien Helmlinger],value:1},
{key:[International,Ania Vercasson],value:1},
{key:[International,Clment Solym],value:2}

]}

Nous avons cette fois demand le dernier niveau, regroup par les deux lments de la cl,
mais nous avons galement effectu un filtre de range de valeurs. Nous avons exig de
retourner uniquement les cls qui se situent entre I et J . Cette range quivaut aux
cls qui sont >= I et <= J. Cela nous permet de retourner uniquement les tags qui
commencent par un I, puisquil ny a aucun tag compos uniquement de la lettre J. Tout ce
qui commence par J sera >J. De plus, nous limitons le rsultat trois laide de
linstruction limit. Nous pouvons donc appliquer quelques filtres nos vues.

Programmation client
Plusieurs bibliothques Python permettent daccder CouchDB, dont la liste est
disponible ladresse suivante :
http://wiki.apache.org/couchdb/Getting_started_with_Python.
Nous allons ici utiliser la bibliothque couchdbkit (http://couchdbkit.org/). Elle est de bonne
qualit et dveloppe par un franais, Benot Chesneau. Nous linstallons avec pip, dans
notre environnement virtuel nosql.
~/python_env/nosql/bin/pip install couchdbkit

La documentation de lAPI est disponible ici : http://couchdbkit.org/docs/api/.


Voyons dabord un exemple trs simple dutilisation. Nous allons insrer notre article de
blog dans la base passerelles :
#!/usr/bin/python
# coding=utf-8

#import datetime

from couchdbkit import *


class Article(Document):

auteur = DictProperty()

titre = StringProperty()
db = Server() .get_or_create_db(passerelles)

Article.set_db(db)
art = Article(

auteur = {prnom: Annie,


nom: Brizard,
e-mail: annie.brizard@cocomail.com},

titre = pourquoi les lphants ont-ils de grandes oreilles ?


)
art.save()

permet lutilisation de classes Python pour reprsenter un document. La classe


couchdbkit
Article que nous crons hrite de la classe couchdbkit.schema.Document. Les types de donnes
compatibles avec CouchDB et qui peuvent tre dclars comme proprits de la classe
sont dans le module couchdbkit.schema. Les plus importants sont repris dans le tableau 7-1.
Tableau 7-1. Types de donnes Couchbdkit

Types Description
StringProperty Une chane Ansi ou Unicode.
IntegerProperty, LongProperty Un entier.
Un nombre rel (correspond aux types float et decimal
FloatProperty, Number, DecimalProperty
en Python).
BooleanProperty Un boolen.
DateTimeProperty, DateProperty, TimeProperty Date complte, date seule et temps seul.

DictProperty
Un dictionnaire, corrrespondant un dictionnaire Python
et un sous-document JSON.
Une liste. La StringListProperty indique que la liste
ListProperty, StringListProperty
est compose uniquement de chanes Unicode.

Nous avons ici utilis un dictionnaire pour le sous-document qui concerne les dtails de
lauteur, et une chane pour le titre. Nous crerons un dictionnaire anonyme au moment o
nous attribuerons les valeurs de proprits. Nous utilisons ensuite lobjet Server pour ouvrir
une connexion. Nous utilisons un constructeur par dfaut car nous nous connectons la
base locale. Nous aurions pu indiquer une URI pour une connexion distante et
optionnellement une taille de batch, cest--dire le nombre de documents retourner en
une fois. La signature partielle du constructeur est la suivante :
def __init__(self, uri=http://127.0.0.1:5984, uuid_batch_count=1000)

Nous utilisons la mthode get_or_create_db() de lobjet Server en lui passant le nom de la


base de donnes. Cette mthode est pratique et dans lesprit de la simplicit des bases
NoSQL. Si vous souhaitez tre plus rigoureux, les mthodes get_db() et create_db() existent
galement. Cette mthode nous retourne une instance de lobjet Database que nous
attribuons notre classe Article par lintermdiaire de la mthode de classe set_db() qui la
stocke dans un attribut de classe (lquivalent dune variable statique).
Nous crons ensuite une instance de notre classe Article et nous en dfinissons ltat dans
le constructeur, puis nous utilisons la mthode save() de linstance du document pour
lenregistrer dans CouchDB.
Nous appelons notre fichier insertion.py et nous lexcutons dans notre environnement.
~/python_env/nosql/bin/python ~/insertion.py

Voil pour ce qui concerne notre exploration de CouchDB. tudions maintenant son
successeur. Beaucoup de choses que nous venons de voir nous seront utiles pour
comprendre comment fonctionne Couchbase Server.

Prsentation de Couchbase Server


CouchDB nest pas nativement distribu. Son architecture est plus adapte de petits
dveloppements qu des applications critiques. En revanche, sa richesse fonctionnelle est
trs intressante.
Paralllement, Membase, un moteur NoSQL orient paires cl-valeur ditribu et en
mmoire, tait une initiative pour crer un systme scalable et trs rapide partir de lide
du serveur de cache, de type memcached. Couchbase Server est la runion de ces deux
moteurs dans un nouveau produit.

Caractristiques
Couchbase Server est architectur sur le modle dAmazon Dynamo : un cluster lastique
et dcentralis. Il est simple dajouter ou de retirer des nuds, et ensuite de lancer une
opration de rebalance, qui va rorganiser les donnes sur le cluster automatiquement.
Couchbase utilise le terme de bucket pour dfinir une base de donnes qui va contenir des
paires cl-valeur. la base, purement des paires cl-valeur la valeur opaque. La
jonction avec CouchDB a fait voluer Couchbase vers un moteur orient documents, qui
reconnat maintenant la valeur comme un document JSON.
Il existe deux types de buckets : memcached ou couchbase. Le bucket memcached offre
un stockage uniquement en RAM, et aucune persistance sur le disque : vous pouvez donc
lutiliser pour btir un systme de cache distribu avec Couchbase. Le bucket couchbase
permet bien sr la persistance sur le disque. Lorsque vous crez un bucket, vous dfinissez
quel est sa taille en mmoire par nud. Cela vous permet de rserver de la RAM par
bucket pour dimensionner votre systme. La mmoire totale du bucket sera donc la valeur
par nud multiplie par le nombre de nuds. Vous indiquez galement un coefficient de
rplication, pour indiquer combien de rplicas vous voulez maintenir sur votre cluster.
Vous ne pouvez videmment pas indiquer un nombre suprieur votre nombre de nuds.
En interne, le bucket est dcoup en vbuckets, selon le principe des vnodes dont nous
avons parl au chapitre 3. Rebalancer le cluster, cela veut dire changer un certain nombre
de vnodes entre nuds.
Laccs aux donnes se fait normalement par la cl : on est ici dans un moteur cl-valeur.
Lors dun get, la cl est passe par une fonction de hachage qui identifie dans quel vbucket
cette cl doit se trouver, et va donc diriger la demande vers un nud. Les bibliothques
Couchbase peuvent tre de type smart client et rcuprer la connexion la topologie
du cluster, pour effectuer des get directement sur le bon nud.

Fonctionnalits CouchDB
Couchbase intgre un certain nombre de fonctionnalits de CouchDB que nous venons de
voir, notamment la cration de documents de design et des vues matrialises qui y sont
contenues. Vous pouvez donc indexer vos donnes. Tout ceci semble trs allchant : un
moteur distribu en mmoire, donc trs rapide, avec toute la richesse fonctionnelle de
CouchDB. Il y a quand mme un ou deux bmols, qui ne sont pas forcment des dfauts
rdhibitoires mais plutt des inconvnients de jeunesse, provenant de lintgration des
deux produits, et qui sont corrigs petit petit au fil des versions.
Premirement, lorsque vous accdez un document par la cl, vous utilisez le protocole
memcached binaire
(https://code.google.com/p/memcached/wiki/BinaryProtocolRevamped) qui est trs
rapide. En revanche, lorsque vous accdez une vue dun document de design, vous
appelez le moteur CouchDB intgr qui va, lui, demander un accs REST, donc beaucoup
plus lent. En fin de compte, lintgration des deux moteurs sest faite sans redvelopper
CouchDB dans le langage de Couchbase. Il y a donc deux moteurs qui sexcutent sur
chaque nud : le moteur Couchbase dvelopp en C++, et le moteur CouchDB en Erlang.
Dailleurs, sur les premires versions de Couchbase, la machine virtuelle Erlang (beam)
avait une constante et intense activit CPU, mme lorsque les nuds ntaient pas
sollicits.
Comme vous accdez au moteur CouchDB, et que celui-ci ne gre aucun cache en
mmoire, vos appels aux vues ne profitent donc pas du stockage en RAM.
Ces quelques exemples vous montrent une chose : si vous voulez utiliser Couchbase
Server, intressez-vous lavancement de lintgration entre Membase et CouchDB dans
la version actuelle, et utilisez Couchbase en connaissance de cause. Toutes les
fonctionnalits noffrent pas les mmes performances. Cest de toute faon une rgle
respecter en gnral : avant de choisir un moteur de bases de donnes pour votre
production, prenez le temps de comprendre son architecture.

Interface dadministration
Un nud Couchbase rpond sur plusieurs ports selon le protocole utilis. Le port 8091 est
utilis pour un accs la console web, qui est un outil graphique dadministration, dont la
page daccueil est prsente sur la figure 7-10.
Figure 7-10
Couchbase Web Console

Vous pouvez y grer votre cluster entier, en vous connectant nimporte quel nud,
puisquil sagit dun systme dcentralis. Longlet Server Nodes (figure 7-11) vous
permet de grer vos nuds, pour enlever, ajouter et rebalancer.

Figure 7-11
Gestion des nuds

Longlet Data Buckets vous permet de grer les buckets et de visualiser les donnes
(figure 7-12) et les vues (figure 7-13).
Figure 7-12
Visualisation des buckets

Figure 7-13
Gestion des vues

La console affiche galement des compteurs et des statistiques par bucket fort utiles
(figure 7-14).
Figure 7-14
Statistiques

Accs Couchbase Server


Rien de surprenant ce ce ct : Couchbase dveloppe des bibliothques daccs pour les
langages les plus importants, en crant des smart clients qui rcuprent la topologie du
rseau en se connectant lun des nuds, ce qui leur permet ensuite daller directement au
bon nud pour un get sur la cl, et qui effectue un appel REST sur les nuds en cas de
requte sur des vues.
Le pilote Python ncessite la bibliothque cliente Couchbase installe. Couchbase publie
un dpt Debian et Ubuntu. Nous rcuprons la cl de signature du dpt.
mkdir couchbase
cd couchbase/

wget http://packages.couchbase.com/ubuntu/couchbase.key

sudo apt-key add couchbase.key

Nous ajoutons ladresse du dpt dans un fichier source apt.


sudo vim /etc/apt/sources.list.d/couchbase.list
>deb http://packages.couchbase.com/ubuntu trusty trusty/main

Et nous installons la bibliothque.


sudo apt-get update

sudo apt-get install libcouchbase2-core libcouchbase-dev

Enfin, nous installons le client Couchbase. Pour nous assurer davoir la dernire version,
nous lobtenons directement depuis son dpt GitHub.
pip install git+git://github.com/couchbase/couchbase-python-client

Voici un exemple simple de code pour accder Couchbase. Nous indiquons la


connexion ladresse de notre serveur Couchbase et le bucket que nous voulons utiliser.
from couchbase import Couchbase
cb = couchbase.Couchbase()

client = cb.connect(beer-sample, 192.168.0.17)

res = c.get(21st_amendment_brewery_cafe-north_star_red, quiet=True)


print res

Loption quiet du get supprime les messages derreur si la cl nest pas trouve.

N1QL
Un dernier mot sur Couchbase. Il sagit dun moteur ambitieux dont le dveloppement est
relativement rapide. Mme sil a encore quelques dfauts de jeunesse, lquipe de
dveloppement travaille ferme pour les corriger. Il sagit dj dun moteur NoSQL
important quil est intressant de suivre. Lune des innovations rcentes est lintroduction
dun langage de requte dclaratif la syntaxe proche du SQL, nomm N1QL (
prononcer comme nickel ).
On sattend donc bien sr un SELECT, etc. Mais nous manipulons du JSON, nest-ce pas ?
Comment exprimer une structure hirarchique ? Couchbase a invent des solutions
ingnieuses pour cela.
Voici deux exemples tirs de la documentation
(http://docs.couchbase.com/prebuilt/n1ql/n1ql-dp4/N1QLRef-DP4.pdf)
SELECT name

FROM contacts
WHERE ANY child IN children

SATISFIES child.age > 14 END

Ici, on cherche lintrieur dun JSON qui comporte des sous-lments nomms children,
avec un lment age. On souhaite donc tous les contacts qui ont au moins un enfant de plus
de dix ans. Si on voulait les contacts dont tous les enfants ont plus de dix ans, on utiliserait
le mot-cl EVERY au lieu de ANY.
SELECT purchases.purchaseId, l.product

FROM purchases

UNNEST purchases.lineItems l
WHERE DATE_PART_STR(purchases.purchasedAt,month) = 4

AND DATE_PART_STR(purchases.purchasedAt,year) = 2014

AND EXISTS (SELECT product.productId


FROM product USE KEYS l.product

WHERE product.unitPrice > 500);

Ici, on utilise la commande UNNEST pour dcomposer les sous-lments dans une sorte de
jointure. Ces sous-lments sont aplatis dans le rsultat qui retourne donc, tout fait
comme avec une jointure traditionnelle, une ligne par lineItems avec les informations de
purchases. Vous voyez galement que les sous-requtes sont supportes : elles agissent sur
les donnes dsimbriques. Cest pour cette raison que lon doit ajouter linstruction USE
KEYS afin dindiquer quelle est la cl de chaque lment.

N1QL est donc un langage adapt pour les donnes hirarchiques, et il sagit dune
innovation trs intressante dans le monde NoSQL.
8
MongoDB

MongoDB est lun des systmes de gestion de donnes NoSQL les plus populaires.
Dvelopp par la socit new-yorkaise MongoDB Inc., il est disponible depuis 2009.
lheure o nous crivons ces lignes, la dernire version disponible est la 2.6.8.

Prsentation
Avant de fonder 10gen (renomme depuis en MongoDB Inc.), Kevin Ryan et Dwight
Merriman avaient dj cr DoubleClick, une entreprise bien connue de publicit en ligne.
Frustrs par limpossibilit de monter en charge comme ils le souhaitaient, ils dcidrent
de dvelopper une plate-forme applicative distribue conue pour le cloud, compose dun
moteur applicatif et dune base de donnes, quils dvelopprent dabord en JavaScript.
Cette ide de plate-forme applicative (un App Engine tel que celui de Google) nintressait
pas grand monde, mais la base de donnes veillait la curiosit, si bien quaprs un an, ils
dcidrent de librer son code. Ce fut ce moment quun net intrt commena se
manifester. Cet engouement se traduisit par une activit importante de dveloppement par
la communaut et un investissement grandissant de la part de 10gen, notamment par le
recrutement dingnieurs spcialiss en SGBD.

Caractristiques
MongoDB est lun des rares systmes de gestion de donnes NoSQL cods avec un
langage qui offre de grandes performances : le C++. Les autres moteurs NoSQL
populaires sont souvent cods en Java ou dans des langages particuliers comme Erlang.
MongoDB Inc. le dfinit comme un SGBD orient documents. le terme documents ne
signifie pas des documents binaires (image ou fichier son, par exemple), mais une
reprsentation structure, comprhensible par MongoDB, dune donne complexe. Plus
simplement, on stocke la reprsentation des donnes comprise par MongoDB. Ce format
est appel BSON (Binary Serialized dOcument Notation ou Binary JSON). Pour
lutilisateur, la structure visible est du JSON (JavaScript Object Notation, un format de
donnes textuel driv de la syntaxe dexpression des objets en JavaScript).

Structure des donnes


Un document BSON reprsente donc lunit stocke par MongoDB, qui quivaut une
ligne dans une table relationnelle. Il est compos dune hirarchie de paires cl-valeur,
sans contrainte de prsence ou de quantit. Le code suivant illustre un exemple de
document bas sur notre application web de test : un site dinformation communautaire,
nomm Passerelles, qui publie des articles sur diffrents sujets, rdigs par les membres
du site et que les lecteurs peuvent valuer et commenter :
{
auteur:

prnom:Annie,
nom:Brizard,

e-mail:annie.brizard@cocomail.com

},
titre:pourquoi les lphants ont-ils de grandes oreilles ?,

mots-cls:

faune,
afrique,
questions intrigantes

],
catgories:
[

sciences,
ducation,
nature

],
date_cration: 12/05/2012 23:30,
statut:publi,

nombre_de_lectures:54,
commentaires:

[
{

date:14/05/2012 10:12,

auteur:fred92@jmenmail.fr,
contenu:il ny a pas que les lphants qui ont des grandes oreilles !

]
}

Vous reconnatrez la syntaxe JSON. Ce document sera stock par MongoDB dans un
format plus compact, plus pratique pour le stockage et les traitements, le BSON. travers
les bibliothques daccs MongoDB et linvite interactive, ce format interne vous est
masqu : vous travaillez dans un JSON lisible. lheure actuelle, la taille maximale dun
document est de 16 Mo.
Les documents sont contenus dans des collections, qui correspondent plus ou moins aux
tables des SGBDR. Mme sil ny a aucune obligation pour les membres dune collection
de partager une structure identique, il est tout de mme plus logique et plus efficace,
parce que cela permettra lindexation de sassurer de cette cohrence. MongoDB na pas
de concept de contraintes comme dans le modle relationnel. Il ny a pas de vrification de
cohrence effectue par le serveur, toute la responsabilit est endosse ce niveau par le
code client. MongoDB stocke les documents tels quil les reoit. De plus, il est inutile de
crer explicitement une collection avant dy insrer des documents, car MongoDB en cre
une ds que le code client la mentionne.
Il y a tout de mme une contrainte ncessaire : chaque document est identifi par une cl
unique dans la collection, tout fait dans le mme esprit que les cls primaires des
SGBDR. Il est bien entendu ncessaire de pouvoir identifier sans ambigut un document
afin deffectuer des mises jour ou des suppressions. La cl porte un nom fixe dans le
document : _id. Sa valeur peut tre fournie ou gnre automatiquement. Cela sapparente
au concept de cls techniques dans les systmes relationnels, la diffrence prs quil ne
sagit pas ici dune incrmentation automatique, mais de la gnration dun UUID (un type
nomm ObjectId dans MongoDB, dune taille de 96 octets), cest--dire une valeur cre
par un algorithme qui garantit une trs faible probabilit de collision (cest ainsi quon
appelle la gnration dun doublon), un peu comme le GUID (Globally Unique IDentifier) de
Microsoft. Cette approche permet dassurer un couplage faible et un fonctionnement
correct dans le cas dune base de donnes distribue.
Les collections peuvent tre regroupes dans des espaces de noms, et sont stockes dans
des bases de donnes (databases). Un espace de noms est simplement un prfixe ajout
aux collections (et spar de celles-ci par un point), qui permet de les regrouper, un peu
comme le concept de schmas de la norme SQL.
Correspondance avec le Schma
Dailleurs, la comparaison avec la norme SQL peut tre pousse. En effet, cette dernire contient dans sa section
ISO/IEC 9075-11:2008 (SQL/Schemata) une dfinition dinformations de catalogue dans le schma
INFORMATION_SCHEMA, notamment implment dans MySQL, MS SQL Server ou PostgreSQL. MongoDB offre un
mcanisme similaire avec un espace de noms system prsent dans chaque base de donnes et qui contient des
collections de mtadonnes.

Une base de donnes peut tre considre comme une collection de collections. Elle est
stocke indpendamment sur le disque, et le concept est assez proche de ce quon appelle
une base de donnes dans le monde relationnel, comme dans MySQL.
Comme pour les collections, ces bases de donnes nont pas besoin dtre pralablement
cres, elles le seront ds quune commande les mentionnera. Il ny a dailleurs pas de
commande pour crer une base de donnes. Il vous suffit dutiliser une base de donnes
(use mabase). Cette approche est trs librale et demande de la rigueur au programmeur au
lieu de lui imposer des garde-fous.

Stocker des objets larges


MongoDB peut galement stocker des documents binaires ou des objets larges, soit
directement dans sa structure BSON, soit laide de GridFS, spcification destine
optimiser la manipulation et la srialisation de fichiers de taille importante. En interne,
MongoDB dcoupe les fichiers en plus petits segments qui seront autant de documents
contenus dans une collection nomme chunks. Les mtadonnes des fichiers sont
conserves dans une autre collection, nomme files. Vous pouvez ajouter des attributs aux
documents de files pour qualifier vos fichiers. La collection chunks contiendra des
documents qui auront un files_id identifiant le document de la collection files, un attribut n
qui est le numro du segment, et un attribut data qui correspond au segment, de type
binaire. Cest une faon optimale de conserver des fichiers par rapport un stockage sur
un systme de fichiers avec des URL. Un outil en ligne de commande, mongofiles, permet
dimporter ou dextraire des documents.

Figure 8-1
GridFS

Le traitement des donnes


Du point de vue transactionnel, MongoDB supporte latomicit seulement lors de la mise
jour dun document. En dautres termes, il y a bien un verrouillage lcriture sur un
document, mais il ne stend pas par dfaut sur une mise jour de plusieurs documents.
En ce qui concerne la durabilit des transactions, elle est assure par une journalisation de
forme WAL, write-ahead log. Les instructions de cration-modification-suppression de
donnes sont en premier lieu crites dans un journal. Si le moteur est arrt proprement,
les critures sont inscrites sur le disque et le journal est supprim. Donc si MongoDB
dmarre et constate lexistence dun journal, cest que le moteur na pas t arrt
correctement. Il excute alors une phase de rcupration qui rejoue le journal. La
journalisation est active par dfaut dans les versions rcentes et 64 bits de MongoDB, elle
peut tre dsactive au dmarrage par loption de la ligne de commande --nojournal. Vous
perdez en scurit et gagnez un peu en performances lors des critures.

Mise en uvre

Installation
Les excutables MongoDB sont disponibles ladresse suivante :
http://www.mongodb.org/downloads. Linstallation sur Windows ou Mac OS X est trs
simple. tant donn que nous disposons dune distribution Ubuntu Server pour nos
exemples, nous pouvons utiliser le paquet mongodb de la distribution officielle (MongoDB
est disponible sur la plupart des dpts officiels des distributions Linux).
Pour rester jour avec les dernires versions, nous allons plutt choisir le paquet ralis
par MongoDB Inc., disponible sur downloads-distro.mongodb.org. Les commandes pour
ajouter le dpt et installer MongoDB sont les suivantes :
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv 7F0CEB10

sudo apt-get install python-software-properties


sudo apt-add-repository deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart

dist 10gen
sudo apt-get update

sudo apt-get install mongodb-org

Le dpt porte toujours le nom de 10gen, mais depuis quelques versions, le paquet
sappelle mongodb-org. Auparavant, son nom tait mongodb-10gen.
Le dpt ubuntu-upstart installe une version du dmon mongodb qui se lance grce au systme
upstart dUbuntu, un systme de lancement de services remplaant le traditionnel dmon
init issu de System-V. Ainsi, le dmarrage et larrt de MongoDB sexcuteront de la
faon suivante :
sudo start mongodb
sudo stop mongodb

sudo restart mongodb


sudo status mongodb

Documentation pour Debian et Ubuntu


Linstallation et le dmarrage sur une distribution Debian ou Ubuntu non upstart sont dcrits ladresse suivante :
http://docs.mongodb.org/manual/installation/.

La configuration du dmon seffectuera ensuite dans le fichier /etc/mongodb.conf. Nous


conservons ici les valeurs par dfaut, qui suffisent pour notre dcouverte de MongoDB.
Vous pourrez galement modifier le script de dmarrage du service : /etc/init/mongodb.conf,
ou encore lancer des dmons manuellement (voir plus loin la section sur la rplication
page 197).

Linvite interactive
Laccs une invite de commandes interactive pour manipuler les donnes de MongoDB
est possible grce au shell mongo (/usr/bin/mongo sur notre Ubuntu). Il sagit dune invite
JavaScript (qui utilise linterprteur V8 depuis la version 2.4 de MongoDB,
SpiderMonkey auparavant) grce laquelle vous pouvez interagir avec MongoDB. Pour
louvrir, tapez simplement mongo dans votre terminal, lexcutable devrait se trouver dans le
chemin. Si vous voulez accder au serveur local qui coute sur le port par dfaut 27017,
cela suffira. Sinon, vous pouvez indiquer ladresse sous la forme suivante : <serveur>:
<port>/<base de donnes>.

Voyons ensuite quelques commandes :


show dbs;

use passerelles;
show collections;

db.articles.find();

it;
Nous affichons tout dabord la liste des bases de donnes. Nous entrons ensuite dans la
base passerelles, nous listons les collections de cette base et enfin nous affichons les dix
premiers objets de la collection articles.
Existence pralable de la base
Mme si la base et la collection ne sont pas cres, vous pouvez excuter les commandes du code prcdent.
Utilisez use passerelles, par exemple, pour entrer dans le contexte de la base passerelles. Si vous demandez un
show dbs, vous ne verrez pas la base passerelles dans la liste tant que vous naurez pas cr un objet lintrieur.

Par la commande it, nous affichons les dix objets suivants. Nous pouvons galement
utiliser une boucle while ou la mthode forEach() de lobjet curseur retourn par find() :
# premire faon

var cur = db.articles.find();

while (cur.hasNext()) printjson(cur.next());


# deuxime faon

db.articles.find().forEach(printjson);

Comme il sagit dun interprteur JavaScript interactif, nous pouvons mlanger du code ou
crer des objets JavaScript pour les insrer dans nos collections, ils seront
automatiquement transforms en BSON par le shell.
Obtention daide
Pour chaque classe ou mthode, vous pouvez demander la mthode .help() qui retournera la liste des mthodes
disponibles ou une aide syntaxique.

Crons par exemple un index sur une valeur de notre structure JSON :
db.articles.ensureIndex({date_cration=-1});

Ici, nous demandons la cration dun index travers un document qui dcrit les cls
participant lindex (ici, lattribut date_cration), lindex peut donc tre composite. Lordre
est ensuite indiqu par 1 (ascendant) ou -1 (descendant). Nous prfrons un ordre
descendant car nous allons plutt requter les articles en les triant par la date de
publication, de la plus rcente la plus ancienne. Les index sont des structures en arbres
quilibrs (B-trees) qui vont permettre des recherches dichotomiques, une structure
traditionnelle des mthodes dindexation. La mthode ensureIndex(), comme son nom
lindique, sassure que lindex est bien prsent. Elle est utile car elle ne cre pas un
deuxime index si lattribut est dj index.
Les index peuvent tre dfinis comme sparse : seuls seront indexs les documents qui
contiennent les attributs spcifis dans lindex.
Insrons notre document. Pour cela, le plus simple est denregistrer la commande
dinsertion avec la structure du document dans un fichier .js, que nous valuerons avec le
shell mongo, soit en le passant la ligne de commande en lanant le shell, soit dans une
session de linvite, par la commande load() :
load(newdoc.js);

Cette commande dinsertion crera simplement un objet JavaScript comprenant notre


document :
var doc = {

auteur:
[]
} ;

Code abrg
Nous avons raccourci le code pour en amliorer la lisibilit. Lintgralit du code est disponible sur www.editions-
eyrolles.com la page consacre au livre.

Utilisons ensuite la mthode insert(), ou mieux, la mthode save() :


db.articles.save(doc);

save() excute un upset, cest--dire quil met jour ou insre selon que la valeur de _id (si
elle est explicite) est trouve dans la collection.
Nous avons vu quelques commandes simples de linvite. Vous trouverez une description
complte du shell sur le site de MongoDB Inc. ladresse :
http://docs.mongodb.org/manual/administration/scripting/. La plupart du temps, vous ne
ferez pas dinsertion laide de linvite, mais partir dun code client. Quittons ce shell en
tapant exit, ou laide de la combinaison de touches Ctrl + D, et voyons comment accder
MongoDB depuis notre code Python.

Programmation client
MongoDB Inc. dveloppe des bibliothques pour de nombreux langages, appels pilotes
(drivers). Celui pour Python se nomme PyMongo, il sagit dun pilote officiel. Avant de
linstaller, nous nous assurons que le paquet python-dev est install sur notre serveur, car il
permettra de compiler les extensions en C du pilote et damliorer sensiblement ses
performances :
sudo apt-get install python-dev

Nous installons ensuite le pilote avec pip, dans notre environnement virtuel nosql :
~/python_env/nosql/bin/pip install pymongo

Voyons un exemple simple dutilisation, dans un fichier source Python, en crant dabord
un dictionnaire Python qui contient le document que nous allons stocker :
#!/usr/bin/python

# coding=utf-8
from datetime import datetime

article = {

auteur:

[]
}

ouvrons une connexion sur mongodb

import sys
import pymongo

from pymongo import Connection

from pymongo.errors import ConnectionFailure


def main():

try:

cn = Connection(host=localhost, port=27017)
print connexion russie
except ConnectionFailure, e:

sys.stderr.write(Erreur de connexion MongoDB: %s % e)


sys.exit(1)

db = cn[passerelles]
assert db.connection == cn
print handle acquis avec succs

db.articles.insert(article, safe=True)

if __name__ == __main__:
main()

Nous avons ici effectu notre criture avec linstruction db.articles.insert(article,


safe=True), ce qui signifie : dans la base de donnes db ouverte, dans la collection articles,
insrer le dictionnaire article. Lobjet sera automatiquement transform en document
JSON par PyMongo. Si la collection articles nexiste pas, elle sera cre.
Encodage dans Python
Nous avons indiqu Python quel est le codage utilis dans le script, sur la deuxime ligne :
# coding=utf-8

Sans cela, Python risque de ne pas pouvoir interprter les signes diacritiques (les caractres accentus) dans le
document.

Le paramtre safe=True indique deffectuer linsertion en mode synchrone. Le pilote


PyMongo effectue linsertion en mode asynchrone par dfaut, ce qui est pour le moins une
option dangereuse pour une application srieuse : une erreur resterait silencieuse. Une
autre option permet de sassurer que lcriture est bien effectue sur un nombre dfini de
nuds dans une configuration en replica set :
db.articles.insert(article, w=2)

Ici, nous indiquons que lcriture doit avoir t rellement effectue sur deux nuds avant
de redonner la main. Cette option implique bien sr le mode synchrone, il est donc inutile
de spcifier safe=True.
Write-concern
Le paramtre w peut tre utilis de diffrentes faons : en spcifiant une tiquette qui indique une rgle prdfinie
ou en utilisant le mot-cl majority pour demander une validation par une majorit de nuds. La majorit est un
nombre de nuds qui volue automatiquement avec le nombre de rplicas.

Il nous suffit donc dexcuter notre fichier Python dans notre environnement (ici, nous
avons appel le fichier insertion.py) :
~/python_env/nosql/bin/python ~/insertion.py

Extraire et chercher
Une requte est crite en JSON et spcifie, laide doprateurs, les valeurs recherches
dans le document. Cherchons ici les articles publis dans la catgorie ducation et qui
comportent le mot-cl afrique :
query = {
mots-cls:afrique,

catgories:ducation

}
Comme vous le voyez, la requte est effectue en crant un document de recherche, qui
dcrit les attributs qui doivent tre prsents pour que le document soit retourn.
Une recherche renvoie un curseur (un objet Cursor) qui permet litration sur les documents
trouvs. La mthode qui retourne ce curseur sappelle find() :
articles = db.articles.find(query)
for article in articles:

print article.get(auteur)

Cette requte peut indiquer un filtrage et un tri des cls des membres retourns :
articles = db.articles.find(

{catgories:ducation}).sort((date_cration, pymongo.DESCENDING))

Correspondance avec le langage SQL


Si on veut tablir une correspondance avec le monde SQL, on peut dire que le filtrage correspond lindication des
colonnes dans le SELECT (ou une projection en algbre relationnelle) et que le sort() correspond un ORDER BY.

Vous pouvez galement utiliser la clause limit(), pour ne retourner quun nombre dfini de
rsultats :
articles = db.articles.find(
{catgories:ducation}).limit(10)

Quand vous avez la certitude que votre requte ne retourne quun seul document, vous
pouvez utiliser la mthode find_one() qui vous conomise le traitement du curseur :
article = db.articles.find_one({mots-cls:afrique,
catgories:ducation,
date_cration: 12/05/2012 23:30})

print article.get(auteur)

Les agrgations
Lun des principaux points faibles de MongoDB (et de beaucoup de moteurs NoSQL) tait
du ct de lanalytique. Souvent, les entreprises qui adoptent un moteur NoSQL pensent
dabord aux besoins oprationnels : maniupler des donnes unitaires en lecture et en
criture. Mais rapidement, lorsque la solution NoSQL est en production, des besoins
analytiques se font sentir : calculer des statistiques et des agrgats sur les donnes. Cela
veut dire avoir un moyen de faire des calculs sur tous les membres dune collection, du
ct serveur, sans avoir rcuprer ces donnes sur le client. Historiquement, MongoDB
offrait la possibilit denvoyer des fonctions MapReduce crites en JavaScript sur le
serveur. Malheureusement, linterprteur JavaScript ct serveur nest pas trs performant.
Pour amliorer les choses, MongoDB a remplac lancien moteur JavaScript
SpiderMondey par V8 de Google. Cest plus rapide, mais pas suffisamment.
Pour cette raison, MongoDB a dvelopp et intgr un moteur dagrgation appel
simplement aggregation (http://docs.mongodb.org/manual/aggregation/). Il est bas sur la
notion de pipeline, qui calcule des agrgats et les envoie ventuellement vers dautres
calculs dagrgats avant de produire le rsultat. La commande aggregate() prend en
paramtre une dfinition dtapes dagrgations et excute le tout sur le serveur. Voici un
exemple simple tir de la documentation :
db.zipcodes.aggregate( [
{ $group: { _id: $state, totalPop: { $sum: $pop } } },

{ $match: { totalPop: { $gte: 10*1000*1000 } } }


] )

Vous y voyez deux oprations, dabord un regroupement effectu sur le champ state des
documents de la collection, avec extraction de la somme de la population par state dans un
champ qui est nomm au passage totalPop (une forme dalias). Ensuite, un filtre $match est
appliqu pour ne conserver que les tats dont la population est suprieure dix millions.
Le filtre $match est lquivalent ici du HAVING en SQL.

Administration
Linterface web dadministration est disponible ladresse http://localhost:28017. Vous
pouvez appeler cette page depuis une machine cliente condition que la configuration de
MongoDB le permette. Dans le fichier /etc/mongodb.conf, vous pouvez indiquer sur quelle
interface le serveur va couter avec loption bind_ip. Pour autoriser un accs partir de
toutes les interfaces, enlevez ou commentez cette ligne de configuration. Vous devez bien
entendu redmarrer le dmon pour que le changement soit pris en compte.
Activation de linterface REST
La plupart des fonctionnalits de linterface dadministration web ncessitent que le dmon mongodb soit dmarr
avec loption REST. Pour cela, activez ou ajoutez la ligne suivante sur Ubuntu :
rest = true

dans /etc/mongodb.conf. Les tches dadministration que requiert MongoDB sont du domaine de ce quon appelle
dans les SGBDR un DBA de production, pas dun DBA tudes. En dautres termes, vous aurez effectuer des
sauvegardes, des restaurations, scuriser laccs, mais vous devrez rarement crer des bases et des schmas de
donnes.

Les oprations dadministration peuvent tre excutes grce linvite interactive ou par
lintermdiaire dun pilote. lintrieur dune base de donnes, un espace de noms
spcial, $cmd, permet de passer des commandes travers sa mthode FindOne(), qui retourne
son rsultat sous forme de document. Beaucoup de ces commandes ont des fonctions
clairement nommes qui les encapsulent. Par exemple, linvite interactive dispose dune
fonction gnrique db.runCommand() et de fonctions spcifiques. Certaines de ces commandes
sont rserves ladministrateur et sont disponibles dans la base de donnes admin
uniquement.
use admin;
db.runCommand(shutdown);

Il y a souvent des fonctions qui encapsulent ces appels :


use admin;

db.shutdownServer();

Vous trouvez galement un client graphique en dveloppement qui est prometteur :


Robomongo. http://robomongo.org/.

Scurit
Quen est-il de la scurit dans MongoDB, dans le sens o on lentend pour tout type de
serveur : authentification et protection des donnes ? Pour lauthentification, la
configuration recommande par MongoDB Inc. est de nen avoir aucune et dexcuter le
ou les nuds MongoDB dans un environnement sr (trusted environment). Cest par la
configuration rseau que vous vous assurez que les ports TCP permettant daccder
MongoDB ne sont accessibles que depuis des machines de confiance. Ces clients peuvent
accder et manipuler les donnes comme bon leur semble.
Utilit pour les besoins simples
Nous avons une fois de plus lillustration du caractre permissif et dcontract de certaines bases de donnes
NoSQL. Elles ne sont pas conues pour stocker et protger des donnes sensibles. Il faut les envisager comme des
dpts de donnes et non comme des systmes de gestion de bases de donnes dans le sens o on lentend
traditionnellement. Cela illustre aussi lintrt de MongoDB en tant que conteneur de donnes pour les sites web,
mme modestes, un peu la manire de MySQL : cela peut tre aussi un outil lger pour des besoins simples.

Au-del de cette libert, MongoDB peut aussi grer une scurit daccs par base de
donnes, trs basique lheure actuelle. Un utilisateur peut tre cr, soit avec toutes les
permissions, soit avec une restriction de lecture seule. La connexion devra tre effectue
en mentionnant les paramtres dauthentification dans la chane de connexion :
mongodb://amelie@ViZiGoth4452@localhost/passerelles?journal=true

Ici, nous indiquons par la chane de connexion que lutilisateur amelie, mot de passe
ViZiGoth4452, se connecte au serveur local, dans la base de donnes passerelles. Nous
ajoutons le paramtre journal=true : la journalisation sera active pour cette session.

Monte en charge
MongoDB se veut un outil pratique rpondant des besoins concrets de dveloppement. Il
est la fois simple utiliser et conu pour sinterfacer de faon naturelle avec les langages
clients orients objet.
Capped collections
Un exemple dadaptation de MongoDB aux besoins courants des infrastructures informatiques est quil inclut un
concept intressant pour le stockage de journaux, quon pourrait traduire en franais par collection bouchonne
(capped collection). Il sagit dune collection la taille fixe, prvue pour offrir dexcellentes performances et qui
agit comme un pile qui maintient automatiquement un nombre fixe dentres, avec un comportement FIFO (First-In
First-Out), un concept similaire au RRD (Round-Robin Database) utilis par des outils comme Nagios. Le nombre
dentres reste constant et au fur et mesure que de nouveaux documents sont insrs, les plus anciens sont
automatiquement supprims.

MongoDB est adapt des besoins modestes de stockage de donnes, mais il est aussi un
systme de gestion de donnes conu au dpart pour tre distribu. Cette distribution est
possible grce deux mcanismes : la rplication, en crant des ensembles de rplicas
(replica sets) et la rpartition (sharding).

Rplication
Un dmon (processus) MongoDB est appel un nud. Dans les situations de production, il
y a en gnral un nud par serveur. Il peut tre utile de monter une machine multinud
pour le dveloppement et les tests.
Ces nuds peuvent tre lis dans un ensemble de rplicas, cest--dire une topologie de
rplication de type matre-esclave telle quon la trouve dans les SGBDR, des fins de
duplication de donnes, et pour assurer une continuit de service, car la rplication inclut
galement un basculement automatique du matre. un moment donn, un nud est
choisi comme matre par MongoDB et reoit donc toutes les critures, quil distribue aux
esclaves. En cas de dfaillance du nud matre, MongoDB bascule automatiquement et
promeut un autre nud matre. Les applications clientes sont averties de ce fait et
redirigent toujours les critures vers le bon matre dans un jeu de rplicas.
Conceptuellement, cette rplication est effectue en mode asynchrone ou synchrone selon
la demande du client. Une opration de modification de donnes peut indiquer le nombre
de rplicas sur lesquels lcriture doit avoir t effectue avec succs avant de rendre la
main, comme nous lavons vu dans les exemples de code prcdents.
Le jeu de rplicas est constitu dun nombre impair de processus, ce qui permet davoir
toujours deux machines qui vont former quorum pour lire un nouveau matre. Si vous
disposez dun nombre pair de nuds, vous pouvez ajouter un arbitre, qui est un dmon
mongod lger dont le but est uniquement de former quorum. Inutile de ddier un serveur
pour larbitre, il peut trs bien tourner sur une machine dj occupe autre chose.
Comme beaucoup de choses en MongoDB, la rplication est aise mettre en place. Il
suffit dabord de dmarrer vos dmons avec loption --replSet <NomDeRplica>, o
<NomDeRplica> est un nom conventionnel que vous choisirez identique pour un jeu de
rplicas. Nous crons un environnement de tests et un jeu de rplicas sur la mme
machine :
sudo mkdir /var/lib/mongodb_datareplica1 /var/lib/mongodb_datareplica2 /var/lib/
mongodb_datareplica3
sudo mongod --dbpath /var/lib/mongodb_datareplica1 --port 15000 --replSet ReplicaSet1

> /tmp/mongo_replica1.log &


sudo mongod --dbpath /var/lib/mongodb_datareplica2 --port 15001 --replSet ReplicaSet1
> /tmp/mongo_replica2.log &

sudo mongod --dbpath /var/lib/mongodb_datareplica3 --port 15002 --replSet ReplicaSet1


> /tmp/mongo_replica3.log &

Sur des machines diffrentes, en situation de production, les options --dbpath et --port ne
seront pas ncessaires.
Connectons-nous avec linvite de commandes sur le premier serveur :
mongo --host localhost:15000

Nous crons un document de configuration, et nous initialisons la rplication :

ce qui retourne :
{

info : Config now saved locally. Should come online in about a minute.,
ok : 1

}
Changement de configuration en production
En situation de production, vous pouvez excuter un rs.initiate() prliminaire sans configuration et ajouter vos
serveurs un un avec la fonction rs.add(serveur), qui encapsule les oprations de changement de
configuration. Mais ici, comme nous voulons que tous nos nuds soient sur la mme machine, nous devons
modifier la configuration en une fois, car MongoDB nous force la faire si nous voulons utiliser localhost comme
nom de machine.

Ensuite, nous pouvons afficher la configuration et le statut de la rplication grce aux


commandes suivantes :
rs.conf()

rs.status()

Modification de linvite
Notons que linvite de commandes change et affiche ReplicaSet1:PRIMARY pour indiquer la connexion non plus
un serveur spcifique, mais au nud primaire du jeu de rplicas.

Notre nud primaire est celui qui coute sur le port 15000. Quittons mongo et arrtons ce
nud pour voir si le basculement fonctionne :
sudo pkill -f datareplica1

Entrons ensuite dans le deuxime serveur mongo et vrifions :


mongo --host localhost:15001
rs.isMaster()

ce qui donne :
{
setName : ReplicaSet1,

ismaster : true,
secondary : false,
hosts : [

localhost:15001,
localhost:15002,

localhost:15000
],

maxBsonObjectSize : 16777216,

ok : 1
}

Il y a bien eu basculement, ce que nous voulions dmontrer. Si ce nud navait pas t


choisi comme matre, vous auriez vu de toute faon un SECONDARY> en invite de commandes.
Le troisime nud aurait t choisi, ce que vous auriez pu vrifier avec un rs.status().

Rpartition (sharding)
La monte en charge horizontale est ralise par rpartition (sharding). MongoDB peut
aussi bien sexcuter en tant que moteur individuel sur une seule machine ou tre converti
en un cluster de donnes clates gr automatiquement et comportant un nombre de
nuds pouvant thoriquement aller jusqu mille. Le sharding de MongoDB impose
quelques limitations lgres ses fonctionnalits, notamment une immutabilit de la cl
(primaire) du document. Le choix de la rpartition est fait par collection. Cest une
collection, et non pas une base de donnes, quon rpartit. Les documents de cette
collection seront distribus aussi quitablement que possible entre les diffrents nuds,
afin dquilibrer les traitements. chaque opration, il faut bien entendu identifier le
nud qui contient ou doit contenir les donnes. Ce rle est assur par un processus
nomm mongos, qui reoit les requtes et les reroute, et qui agit donc comme un rpartiteur
de charge. Pour assurer une continuit de service, cette rpartition peut tre accompagne
de rplication : chaque nud peut avoir son propre groupe de rplicas avec basculement
automatique.

Figure 8-2
Le modle de rpartition de MongoDB (Source : documentation officielle, http://docs.mongodb.org/manual/sharding/)

La configuration de la rpartition est maintenue par un ou plusieurs serveurs de


configuration. MongoDB Inc. recommande den avoir trois, car le protocole de
synchronisation entre les serveurs de configuration est optimis pour trois serveurs.
Installer la rpartition consiste :
1. Dmarrer des dmons mongod avec loption --shardsvr.
2. Dmarrer un ou plusieurs dmons mongod avec loption --configsvr pour en faire des
serveurs de configuration.
3. Dmarrer un ou plusieurs serveurs mongos : mongos --configdb <serveur>:<port>. Ladresse des
serveurs de configuration est passe en paramtre au dmarrage de mongos.
4. Se connecter un serveur mongos pour configurer les shards.
Voici un exemple en code de la configuration sur une seule machine qui simulera un
environnement de rpartition. Premirement, nous lanons les diffrents nuds.
sudo mkdir /var/lib/mongodb_data1 /var/lib/mongodb_data2

sudo chown -R mongodb.mongodb /var/lib/mongodb_data1

sudo chown -R mongodb.mongodb /var/lib/mongodb_data2


sudo mongod --shardsvr --dbpath /var/lib/mongodb_data1 --port 10000 > /tmp/shard1.log

&

sudo mongod --shardsvr --dbpath /var/lib/mongodb_data2 --port 10001 > /tmp/shard2.log


&
Vrifions que tout sest bien pass :
cat /tmp/shard1.log
cat /tmp/shard2.log

Puis nous lanons un serveur de configuration :


sudo mkdir /var/lib/mongodb_config
sudo chown -R mongodb.mongodb /var/lib/mongodb_config

sudo mongod -configsvr --dbpath /var/lib/mongodb_config --port 20000 > /tmp/mongo_

config.log &
cat /tmp/mongo_config.log

Et enfin nous crons le dmon mongos :


sudo mongos --configdb localhost:20000 > /tmp/mongos.log &

cat /tmp/mongos.log

En lisant les messages envoys dans /tmp/mongos.log au dmarrage, nous voyons que cest le
dmon mongos qui coute sur le port 27017, le port par dfaut du serveur MongoDB. Un
client accdera donc au serveur mongos qui soccupera de rediriger les commandes sur le
bon shard.
Bien entendu, ce nest pas termin, nous navons pas indiqu que les deux dmons mongod
que nous avons dmarrs sont des nuds. Pour cela, nous devons nous connecter sur le
serveur mongos en invite de commandes en tapant mongo, qui montrera une invite mongos> puis,
dans linvite :
use admin

db.runCommand( { addshard : "localhost:10000" } )


db.runCommand( { addshard : "localhost:10001" } )

Nous activons ensuite la rpartition pour la base de donnes passerelles :


db.runCommand( { enablesharding : "passerelles" } )

Nous devons ensuite choisir une cl de rpartition pour nos collections, cest--dire une
reprsentation des lments dun document qui dtermine la segmentation. Il sagit
simplement dune liste dattributs (un ou plusieurs), par exemple :
{ "date_cration": 1; "catgories": 1 }

Ici, nous dcidons de rpartir par date de cration et par catgorie darticles. Il est
important de choisir une bonne cl ds le dbut, car les changements postrieurs seront
probablement douloureux. Nous choisissons une cl suffisamment fine pour donner
MongoDB les moyens dtablir une rpartition aussi quitable que possible. Une
rpartition sur la date de cration seule est possible, et suffisante car les articles seront
logiquement ajouts rgulirement au fil du temps. Cependant, dans le cas dune
importation en masse darticles qui porteraient tous la mme date, MongoDB naurait
dautre choix que de charger une partition au dtriment des autres.
Nous utilisons cette cl pour rpartir une collection laide de la commande
shardcollection :

use admin
db.runCommand( { shardcollection : "passerelles.articles", key : { "date_cration": 1,

"catgories": 1 } } );
La configuration est termine, MongoDB soccupera ensuite de rpartir automatiquement
les donnes au mieux entre les shards. La configuration pourra tre vrifie dans les
collections de la base de donnes config, qui contient toutes les mtadonnes de la
rpartition :
mongos> use config

mongos> show collections

mongos> db.collections.find()
{ "_id" : "passerelles.articles", "lastmod" : ISODate("1970-01-16T10:32:54.791Z"),

"dropped" : false, "key" : { "date_cration" : 1, "catgories" : 1 }, "unique" : false }

Voil pour ce qui concerne notre exploration de MongoDB.


9
Riak

Riak est un moteur NoSQL dcentralis, fond sur les principes de Dynamo dAmazon,
qui offre dexcellentes performances. Il a t cr et dvelopp par la socit Basho.
La grande force de Riak est sa capacit monter en charge simplement, en ajoutant de
nouvelles machines au cluster. Riak distribue automatiquement les donnes entre les
machines du cluster.

Mise en uvre

Installation
Riak est disponible en tlchargement sur le site de la socit Basho, ladresse suivante :
http://wiki.basho.com/Installation.html. Les tapes de linstallation sont clairement
dtailles par environnement. Nous prsentons ici la mthode adapte Debian et Ubuntu.

Installation du paquet
Avant toute chose, il convient dinstaller une version spcifique de la bibliothque SSL.
lheure o nous crivons ces lignes, Riak utilise la version 0.9.8 de la bibliothque libssl.
Les versions rcentes de nos distributions intgrent au moins la version 1 de libssl. Nous
pouvons le vrifier en effectuant une recherche dans les paquets grce la commande
suivante :
sudo dpkg -S libssl

Il nous faut donc installer une version antrieure. Ceci peut tre fait sans danger, car
plusieurs versions de libssl peuvent tre installes sur le mme systme.
sudo apt-get install libssl0.9.8

Ensuite, nous tlchargeons Riak ladresse http://wiki.basho.com/Installing-on-Debian-


and-Ubuntu.html et nous linstallons.
wget http://downloads.basho.com.s3-website-us-east-1.amazonaws.com/riak/CURRENT/

ubuntu/precise/riak_1.2.1-1_amd64.deb

Puis nous installons le paquet :


sudo dpkg -i riak_1.2.1-1_amd64.deb

Installation des sources


Pour notre exemple, nous avons effectu linstallation partir des sources, le paquet
ntant pas encore disponible. Pour ce faire, nous avons dabord install les paquets
ncessaires la compilation et Erlang :
sudo apt-get install build-essential libc6-dev git libncurses5-dev openssl libssl-dev
wget http://erlang.org/download/otp_src_R15B01.tar.gz

tar zxvf otp_src_R15B01.tar.gz

cd otp_src_R15B01
./configure && make && sudo make install

Puis nous avons tlcharg et compil les sources de Riak :


wget http://downloads.basho.com.s3-website-us-east-1.amazonaws.com/riak/CURRENT/riak-

1.2.1.tar.gz
tar zxvf riak-1.2.1.tar.gz

cd riak-1.2.1
make rel

Si le make se termine sans erreur, Riak compil sera disponible dans le sous-rpertoire rel
du rpertoire dans lequel vous avez lanc le make. Vous pouvez ensuite le copier dans un
rpertoire adquat de votre systme.
sudo mv rel /usr/local/riak-1.2.1
cd /usr/local/riak-1.2.1/riak/bin
./riak start

./riak ping
pong

La commande riak ping permet de dterminer simplement si le serveur est dmarr. Un pong
est retourn en cas de succs.

Configuration
Les fichiers de configuration de Riak se trouvent dans le rpertoire etc/. Pour notre
installation exemple, il sagit de /usr/local/riak-1.2.0/riak/etc. Dans une installation binaire,
vous les trouverez plus probablement dans /etc/riak. La configuration gnrale se trouve
dans le fichier app.config. Les deux principales sections sont riak_api, qui dfinit les options
pour accder Riak via Protocol Buffers, et riak_core, qui dfinit la configuration gnrale
et laccs par HTTP. Pour ouvrir laccs linterface REST de Riak depuis des machines
clientes, nous allons modifier le code :
{riak_core, [


{http, [ {"127.0.0.1", 8098 } ]},

par :
{http, [ {"0.0.0.0", 8098 } ]},

Nous relanons ensuite Riak :


cd /usr/local/riak-1.2.0/riak/bin

./riak start
Un accs Riak via un navigateur web retourne la liste reprsente la figure 9-1, il sagit
de la liste des ressources REST disposition.

Figure 9-1
Liste des ressources REST disposition

Utilisation de lAPI REST


Accdons Riak en utilisant curl. Pour tester laccs Riak, nous pouvons utiliser la
commande ping via linterface REST :
curl -v http://localhost:8098/ping

Nous recevons la rponse :


* About to connect() to localhost port 8098 (#0)
* Trying 127.0.0.1 connected
* Connected to localhost (127.0.0.1) port 8098 (#0)

> GET /ping HTTP/1.1

> User-Agent: curl/7.21.6 (i686-pc-linux-gnu) libcurl/7.21.6 OpenSSL/1.0.0e


zlib/1.2.3.4 libidn/1.22 librtmp/2.3

> Host: localhost:8098

> Accept: */*


>

< HTTP/1.1 200 O

< Server: MochiWeb/1.1 WebMachine/1.9.0 (someone had painted it blue)


< Date: Tue, 13 Nov 2012 11:03:56 GM

< Content-Type: text/html

< Content-Length:
<

* Connection #0 to host localhost left intact

* Closing connection #0
OK
Lquivalent Riak dune table contenant des donnes sappelle un bucket. Il est inutile de
crer un bucket, sa cration sera automatique lors de la premire insertion de donnes.
Nous allons insrer notre article de blog du site Passerelles :
curl -X PUT -H Content-Type: application/json -d
{

auteur:

{
prnom:Annie,

nom:Brizard,

e-mail:annie.brizard@cocomail.com
},

titre:pourquoi les lphants ont-ils de grandes oreilles ?

} http://localhost:8098/buckets/passerelles/keys/1?returnbody=true

Comme nous lavons demand par (returnbody=true), nous recevons le document en retour.
Interrogeons maintenant notre bucket :
curl -X GET http://localhost:8098/buckets/passerelles/keys?keys=true

Nous recevons la liste des cls, en format JSON :


{keys:[1]}

Il est possible de recevoir la liste des cls dans un flux pour permettre au client de le traiter
par paquets :
curl -X GET http://localhost:8098/buckets/passerelles/keys?keys=stream

Retrouvons maintenant le document lui-mme :


curl -X GET http://localhost:8098/buckets/passerelles/keys/1

Puis supprimons-le :
curl -X DELETE http://localhost:8098/buckets/passerelles/keys/1

Programmation client
Nous allons utiliser Riak avec Python en utilisant le client Python dvelopp par Basho.
./python_env/nosql/bin/pip install riak

En interne, ce client utilise linterface REST ou protobuf. Nous allons bien sr prfrer
protobuf pour ses meilleures performances. Voici un premier morceau de code qui nous
connecte au serveur, insre notre article sur le site Passerelles, puis rcupre la liste des
cls du bucket passerelles.
#!/usr/bin/python

# coding=utf-8

import riak
import json

cli = riak.RiakClient(host=192.168.0.22, port=8087, transport_class=riak.

RiakPbcTransport)
pas = cli.bucket(passerelles)

article = pas.new(1, data={


auteur:

{
prnom:Annie,

nom:Brizard,
e-mail:annie.brizard@cocomail.com
},

titre:pourquoi les lphants ont-ils de grandes oreilles ?

})
article.store()

print pas.get_keys()

Le retour est une liste de cls :


[1]

Nous pouvons obtenir le document de la faon suivante :


article = pas.get(1).get_data()

La mthode get() retourne un objet Riak, et la mthode get_data() de cet objet retourne un
dictionnaire Python. Nous gnrons donc directement un dictionnaire.

Administration
Riak est trs simple administrer. Il sagit aprs tout dun dpt de paires cl-valeur dans
la ligne de Dynamo, offrant un serveur largement autoconfigur aux fonctionnalits
simples et efficaces. Comme Riak est par nature un systme distribu, nous allons voir
comment grer les nuds du cluster.

Configuration du nud
La configuration du premier nud implique de modifier les fichiers de configuration et
dutiliser loutil riak-admin pour crer un cluster. Premirement, nous devons stopper Riak,
sinon on ne pourra plus y accder aprs changement des fichiers de configuration.
sudo ./riak stop

Nous fixons lIP sur laquelle coute Riak pour indiquer une IP lie une interface de notre
serveur. Nous allons le faire aussi bien pour Protocol Buffers (section riak_api) que pour
linterface HTTP :
{riak_api, [

{pb_ip, 192.168.0.22},

{riak_core, [

{http, [{192.168.0.22, 8098}]},

Puis nous modifions galement le nom au niveau de la machine virtuelle Erlang, dans le
fichier vm.args. Nous changeons la ligne :
-name riak@127.0.0.1

en :
-name riak@192.168.0.22

Nous redmarrons ensuite Riak :


sudo ./riak start

Si la tentative de dmarrage du nud provoque une erreur, vous pouvez obtenir plus
dinformations en activant les messages de la console Erlang :
sudo ./riak console

rm -rf /var/lib/riak/ring/*

La premire machine va tre automatiquement membre du cluster, vous aurez configurer


les autres machines pour joindre ce cluster. Pour obtenir une liste des membres du cluster,
utilisez loutil riak-admin de la faon suivante :
./riak-admin status | grep ring_members

Dans notre cas, avec une seule machine, le retour est :


ring_members : [riak@192.168.0.22]

Pour ajouter une nouvelle machine au cluster, configurez le nud, puis rejoignez le cluster
laide de riak-admin :
sudo ./riak-admin cluster join riak@192.168.0.22

sudo ./riak-admin cluster plan


sudo ./riak-admin cluster commit

Voil pour ce qui concerne notre exploration de Riak.


10
Redis

Redis est un moteur de base de donnes en mmoire (on pourrait lappeler un serveur de
structure de donnes) dvelopp la base par un programmeur italien nomm Salvatore
Sanfilippo. Son dveloppement partir de 2009 a t trs rapide et sa popularit fut
foudroyante. En 2010, VMWare recruta Salvatore, puis Pieter Noordhuis, un contributeur
important de Redis, pour travailler plein temps sur le dveloppement du produit, tout en
le laissant en licence libre (BSD).

Prsentation
Redis est un moteur non relationnel qui travaille principalement en mmoire. Son objectif
est de manipuler le plus rapidement possible les structures de donnes qui y sont
maintenues. Il est la fois un outil de gestion de paires cl-valeur et un cache de donnes
la manire de memcached. En effet, il offre les mmes fonctionnalits et avantages que
memcached, mais avec un modle beaucoup plus riche et solide. Le but de Redis est dtre
trs rapide, trs efficace et lger. Et il remplit ses objectifs la perfection. Cest de plus un
outil avec lequel il est trs agrable de travailler. En gnral, quand on lessaie, on
ladopte.
memcached
memcached est un systme de cache dvelopp lorigine par les dveloppeurs de LiveJournal, un outil de cration
de blogs, trs utilis dans les dveloppements web par beaucoup de grands acteurs comme Twitter et Facebook, ou
des sites comme Wikipdia. Les structures de donnes manipules par memcached sont trs simples : il sagit de
paires cl-valeur, donc des tableaux de hachage, aussi appels maps. memcached noffre aucune persistance.

Les types de donnes


Redis ne manipule pas de documents au sens o on la entendu jusqu prsent, par
exemple des structures JSON. Il travaille en paires cl-valeur, les valeurs pouvant tre de
cinq types, dtailles dans les sections suivantes.

Chanes
Une chane de caractres en Redis est un peu plus quune chane. Elle permet galement
de stocker correctement les valeurs numriques et binaires (binary safe), ce qui la rend
adapte pour les calculs ou les fichiers binaires comme des images. La taille maximale
supporte par ce type est de 512 Mo. Redis offre nativement un certain nombre de
commandes qui permettent de manipuler les chanes et de les utiliser de diverses faons,
par exemple en modifiant la valeur numrique quelles contiennent avec des commandes
comme INCR, INCRBY ou DECR et DECRBY.

Listes
Les listes sont simplement des listes de chanes chanes au sens large de Redis comme
nous venons de le voir dans la section prcdente maintenues dans un ordre dfini
linsertion. Lorsque vous ajoutez une chane la liste, vous pouvez dfinir si vous voulez
lajouter au dbut ( gauche) ou la fin ( droite) de la liste, laide des commandes LPUSH
(gauche) ou RPUSH (droite).

Ensembles
Un ensemble (set) est une collection non trie de chanes. Il reprsente un ensemble
correspondant plus ou moins ce que la thorie des ensembles entend par un set : il est
non tri et naccepte pas les doublons. Si vous insrez une valeur dj prsente, cela
naura aucun effet. Laccs un lment de lensemble offre dexcellentes performances
mme si lensemble contient un grand nombre dlments. Le nombre dlments est
limit un entier 32 bits non sign, cest--dire 232 1. Quelques oprateurs ensemblistes
sont disponibles au niveau du serveur pour effectuer des oprations trs rapidement :
union, intersection et diffrence.

Hachages
Ils reprsentent une table de hachage (un dictionnaire), ce qui permet de stocker une
reprsentation dobjet, limage dun document JSON plat (non hirarchique), dans
Redis. Le stockage est optimis, ce qui fait que le hachage prend peu de place en mmoire.

Ensembles tris
Lexpression ensemble tri sonne un peu comme un oxymore, mais le rsultat fait
sens. Lensemble tri se comporte comme un ensemble mais chaque membre est en plus
associ une note (un score) qui permet de trier lensemble. Plusieurs membres peuvent
avoir la mme note. La manipulation et le tri sont trs rapides. Il est ceci dit inutile de
mentionner ce genre de choses : tout est trs rapide en Redis. Avec un ensemble tri, vous
pouvez grer avec une grande efficacit tout type dordre ou de score, du genre jeux, tops
ou best of.

Mise en uvre
Redis est une perle : efficacit, lgance et simplicit. Tout ce que nous allons voir dans
les sections suivantes sera donc trs facile implmenter.

Installation
Linstallation de Redis est trs simple. Tout dabord, tlchargez la dernire version
disponible du moteur ladresse suivante : http://redis.io/download. Nous avons
tlcharg la version 2.6.0 release candidate 5 qui tait la dernire version au moment de
la rdaction de ce chapitre. Nous lavons ensuite dcompresse et nous avons compil le
moteur.
wget http://redis.googlecode.com/files/redis-2.6.0-rc7.tar.gz
tar xvzf redis-2.6.0-rc7.tar.gz

cd redis-2.6.0-rc7
make

Redis est dvelopp en C, il est donc ncessaire dinstaller au pralable un compilateur C


comme GCC pour que la compilation se droule correctement.
Redis est galement disponible sous forme de paquets dans plusieurs distributions. Sur
Debian et Ubuntu, le paquet sappelle redis-server, il est disponible dans les dpts
officiels. Vous pouvez linstaller ainsi :
sudo apt-get install redis-server

Cette installation par paquet lavantage de placer Redis dans les bons rpertoires sur
votre distribution. En revanche, vous nobtiendrez pas la dernire version du moteur.
Compte tenu de la simplicit de compilation et dinstallation de Redis, nous vous
conseillons de raliser une installation manuelle. Aprs compilation, vous pouvez dplacer
manuellement les quelques excutables ncessaires Redis :
sudo cp redis-server redis-cli redis-benchmark /usr/local/bin

Pour dmarrer le serveur Redis, vous pouvez simplement invoquer lexcutable redis-
server. Les quelques paramtres disponibles permettent dindiquer un port sur lequel
couter (le port par dfaut est le 6379), une relation de serveur secondaire par rapport un
serveur matre, ou lemplacement du fichier de configuration prendre en compte. Voici
des exemples de lancement du serveur Redis :
nohup redis-server /etc/redis/redis.conf --loglevel verbose &
nohup redis-server --port 7777 --slaveof 127.0.0.1 8888 &

Pour sassurer que Redis est lanc, lancez un ping laide du client redis-cli. Il devrait vous
renvoyer un PONG.
>redis-cli ping

PONG

Configuration
Si vous avez besoin dajuster la configuration de Redis, un fichier de configuration peut
tre cr et indiqu au dmarrage du serveur. Un fichier dexemple (redis.conf) est
disponible dans les sources, cette adresse : https://github.com/antirez/redis. Nous verrons
plus en dtail certains lments de la configuration plus tard, attardons-nous dj sur les
plus vidents. Voici un exemple de fichier de configuration simple :
daemonize yes

port 6379
bind 127.0.0.1

timeout 120

loglevel notice
logfile s/var/log/redis.log

syslog-enabled no
databases 16

Par dfaut, Redis ne tourne pas en tant que dmon, cest la raison pour laquelle dans notre
exemple de lancement de redis-server, nous avons lanc le processus en arrire-plan
laide du caractre &. En indiquant daemonize yes, nous pouvons faire en sorte que Redis
dmarre en tant que dmon. Le port et lIP sur lesquels Redis coute sont ensuite dfinis.
6379 est le port par dfaut, et si loption bind nest pas indique, Redis rpondra sur toutes
les interfaces. Loption timeout permet de fermer une connexion inactive, ici aprs 120
secondes. La valeur par dfaut est 0, pas de timeout. Ensuite, nous trouvons quelques
options de journalisation de lapplication : ici nous dfinissons le niveau de journalisation
notice, qui est un niveau adapt pour la production, et nous indiquons le fichier de
journal. Une autre option est denvoyer les informations stdout. Nous dcidons de ne pas
les traiter par syslog. Finalement, nous indiquons le nombre de bases de donnes : 16. En
Redis, une base de donnes est simplement un espace de stockage de paires cl-valeur en
mmoire identifi par un numro. La base de donnes par dfaut est 0.

Utilisation de redis-cli
Redis est livr avec une invite interactive nomme redis-cli, qui permet denvoyer des
commandes au serveur. Utilisons-la pour stocker notre entre de blog Passerelles :
redis-cli
redis 127.0.0.1:6379> SELECT 1
OK

redis 127.0.0.1:6379[1]>HMSET article:1 prenom Annie nom Brizard e-mail annie.


brizard@cocomail.com titre Ce sont les girafes qui ont de grandes oreilles, non ?
OK

redis 127.0.0.1:6379[1]> SADD tag:animaux 1


(integer) 1
redis 127.0.0.1:6379[1]> SADD tag:questions 1

(integer) 1

redis 127.0.0.1:6379[1]> SADD article:1:tags animaux questions


(integer) 2

redis 127.0.0.1:6379[1]> SINTER tag:animaux tag:questions

1) 1
redis 127.0.0.1:6379[1]> HVALS article:1

1) Annie

2) Brizard
3) annie.brizard@cocomail.com

4) Ce sont les girafes qui ont de grandes oreilles, non ?

redis 127.0.0.1:6379[1]> HGET article:1 e-mail


annie.brizard@cocomail.com

redis 127.0.0.1:6379[1]> MULTI

OK
redis 127.0.0.1:6379[1]> RENAMENX article:1 article:2

QUEUED

redis 127.0.0.1:6379[1]> SREM tag:animaux 1


QUEUED

redis 127.0.0.1:6379[1]> SREM tag:questions 1


QUEUED

redis 127.0.0.1:6379[1]> SADD tag:animaux 2


QUEUED
redis 127.0.0.1:6379[1]> SADD tag:questions 2

QUEUED

redis 127.0.0.1:6379[1]> EXEC


1) (integer) 1

2) (integer) 1

3) (integer) 1
4) (integer) 1

5) (integer) 1
redis 127.0.0.1:6379[1]>

redis 127.0.0.1:6379[1]> TYPE article:2


hash

Comme vous le voyez, Redis comporte un ensemble de commandes trs simples, qui
permettent principalement de manipuler les types de donnes disponibles. La liste des
commandes est disponible ladresse suivante : http://redis.io/commands.
Voyons rapidement les commandes utilises.
SELECT Change le contexte de la base de donnes. Ici, nous joignons la base de donnes
1.
HMSET Attribue des valeurs un hachage. Ici, nous stockons notre article article:1.
SADD Ajoute un ou plusieurs membres un ensemble. Si la cl nexiste pas, elle sera
cre, sinon le membre sera ajout la cl existante. Nous lutilisons ici pour ajouter des
tags notre article : nous maintenons des tags sous forme densembles dont la cl est
tag:<nom_du_tag>, et nous ajoutons les identifiants darticles qui portent ce tag comme
membres de lensemble.
Pour rfrence, nous crons aussi un ensemble article:1:tags pour lister les tags de
larticle. Il sera plus simple de retrouver les tags partir dun article de cette manire.
SINTER Effectue une intersection entre deux ensembles. Ici, nous voulons savoir quels
sont les identifiants darticles prsents la fois dans tag:animaux et tag:questions. Redis
nous retourne "1".
HVALS Retourne la table de hachage complte contenue dans une cl.
HGET Retourne un lment dune table de hachage. Ici, nous retrouvons le-mail de
lauteur de larticle 1.
MULTI Commence une transaction. Toutes les instructions qui suivent seront maintenues
dans une file dattente et ne seront excutes qu lappel de la commande EXEC. Le
rsultat des commandes suivantes sera donc QUEUED. Pour annuler la transaction, utilisez
la commande DISCARD. Par transaction, il faut simplement entendre une file dattente. Rien
nest excut avec lEXEC, mme pas les commandes de lecture. Nous maintenons cette
transaction car nous avons dcid de changer la cl de larticle.
RENAMENX Renomme une cl.
SREM Supprime un membre dans un ensemble.
EXEC Valide la transaction et excute toutes les commandes dans la file.
TYPE Retourne le type de donne contenu dans la cl. Ici, un hash.

Exemples dapplications clientes


Nous allons dvelopper une application cliente en Python. Comme vous en avez
maintenant lhabitude, nous allons installer le client Redis pour Python
(http://pypi.python.org/pypi/redis/).
~/python_env/nosql/bin/pip install redis

Au lieu dutiliser lexemple traditionnel de notre blog Passerelles, nous allons raliser un
code utilisable par tous, petit par la taille mais grand par la puissance. En quatre lignes de
code (sans compter limportation des modules et une ligne de dbogage), le script Python
suivant suit le flux public de Twitter et rcupre des tweets concernant quelques mots-cls,
ici "nosql", "sql" et "redis".
#!/usr/bin/python

import redis
import tweetstream

words = ["nosql", "sql", "redis"]


r = redis.StrictRedis(host=localhost, port=6379, db=2)
stream = tweetstream.FilterStream("user", "password", track=words)

for tweet in stream:


if tweet.has_key("text"):
print tweet[user][screen_name] + ": " + tweet[text] , "\n"

r.set(tweet[id], tweet[text])

Nous crons dabord une liste de mots-cls surveiller, puis nous ouvrons une connexion
Redis en instanciant la classe redis.StrictRedis. Cette classe sappelle strict car elle tente
autant que possible de respecter la syntaxe officielle des commandes Redis. Nous
passons les informations de connexion au constructeur.
Pour suivre le flux Twitter, nous instancions la classe tweetstream.FilterStream (le module
tweetstream est document ladresse suivante : http://pypi.python.org/pypi/tweetstream).
Nous bouclons ensuite dans les tweets du flux, et comme il sagit dun flux, le contact
restera ouvert et la boucle continuera attendre de nouveaux tweets tant que le script ne
sera pas tu.
Pour cet exemple de code, nous avons ajout une ligne de dbogage qui ralise un print du
tweet repr. Ensuite, la ligne qui insre le tweet dans un string est la suivante :
r.set(tweet[id], tweet[text])

Nous utilisons lidentifiant Twitter du tweet comme cl. Ce nest pas forcment une trs
bonne ide, nous pourrions plutt utiliser une combinaison date-auteur, par exemple, mais
cela suffira pour notre exemple.
Nous avons laiss tourner ce code quelques jours. En utilisant le client Redis, nous
pouvons tester la taille de la base, cest--dire le nombre de cls, laide de la commande
DBSIZE, qui retourne 15171. La mthode dbsize() de lobjet StrictRedis en Python retourne la
mme valeur. Voici du code Python qui affiche la taille de la base de donnes et retrouve
tous les tweets.
#!/usr/bin/python

import redis
r = redis.StrictRedis(host=localhost, port=6379, db=0)

print r.dbsize()

for key in r.keys(*):


print r.get(key)

Nous utilisons ici la mthode keys() qui retourne une liste de cls correspondant un
pattern de recherche, ici * pour toutes les cls, puis nous bouclons et affichons chaque
lment laide de la mthode get(). Un fragment de retour dans la console est affich ci-
dessous :
Know anyone for this job? SQL Report Developer in Naperville, IL http://t.co/R8GqJwiV

T-SQL MERGE Statement Tips http://t.co/eQBcmKSb by @ItzikBenGan @sqlservermag


#SQLServer
RT @couchbase: The scalability &amp; performance needs of todays apps differs

dramatically from the past. New whitepaper on why #NoSQL:


#Jobs #jobsite Graduate Consultant - Leading Software Company (Java, XML, SQL)
http://t.co/YoAwxhy4 #Fishajobs

#SQL #Database #Jobs Sql Database Administrator at Unc Charlotte (Charlotte, NC)
http://t.co/jRznyw4h
SQL Back End Lead /Developer - 6 Month Rolling Contract - http://t.co/HTQoaUra

#jobs #london #dev #it


@IwilBeThere Lee tutoriales SQL Injected, mira videos si queres jaja

#Job, Oracle BPM Developer with :CSS,HTML,Java,Oracle,SOA,SQL http://t.co/iqgoHhEl


BlackNova Traders SQL Injection: BlackNova Traders, a web-based game similar to the

BBS game TradeWars, suffers http://t.co/E6cL2GFt

Voici brivement un autre exemple de code Python, stockant un hachage. Le pilote Python
convertit automatiquement un dictionnaire Python en table de hachage Redis, pour le
stocker laide de la mthode hmset(), ou le restituer laide de la mthode hgetall().
#!/usr/bin/python

import redis
r = redis.StrictRedis(host=localhost, port=6379, db=1)

r.hmset(contact:ajar, dict(

prenom=Emile,
nom=Ajar,

Profession=Ecrivain

)
)

dic = r.hgetall(contact:ajar)

print dic
Pub/sub
Redis permet aussi de grer des canaux dinformation, correspondant au pattern de
messagerie publish-subscribe : un client sabonne un canal, il peut ainsi y envoyer des
publications et recevoir les messages des autres abonns. Les commandes de Redis
permettant de grer ces canaux sont trs simples : SUBSCRIBE, UNSUBSCRIBE et PUBLISH. Nous
allons transformer notre code de suivi de flux Twitter pour envoyer un message sur un
canal et avertir dautres clients Redis. Le code du serveur de message est le suivant :
#!/usr/bin/python
import redis

import tweetstream

words = ["nosql", "sql", "redis"]


r = redis.StrictRedis(host=localhost, port=6379, db=1)

stream = tweetstream.FilterStream("user", "password", track=words)


for tweet in stream:

if tweet.has_key("text"):
r.publish(mytwitter, tweet[text])

Nous reprenons lessentiel du code. La seule diffrence est laction ralise vers Redis la
rception dun tweet : nous effectuons simplement un publish() sur le canal mytwitter avec le
corps du tweet. Nous excutons le script, qui va tourner jusqu interruption manuelle.
Nous lanons ensuite le script suivant :
#!/usr/bin/python
import redis
import tweetstream

words = ["nosql", "sql", "redis"]


r = redis.StrictRedis(host=localhost, port=6379, db=1)
ps = r.pubsub()

ps.subscribe("mytwitter")

for msg in ps.listen():


print msg[data]

Il sagit bien sr du client. Un objet pubsub est instanci et nous appelons la mthode
subscribe() pour labonner notre canal. Il suffit ensuite de boucler sur la mthode listen()
pour rcuprer petit petit les publications de notre autre script. Voici un extrait du
rsultat, apparaissant au fur et mesure de larrive des tweets :
@ToonyHouusni oulalalaa jsais pas jte redis aprs atta

SQL Server Reporting Analyst: Robert Half Technology is looking for a SQL Server
Reporting Analyst for http://t.co/jaFIdCri #job #rht

@BelieberBoyPOL bo ja chodze do sql.xd ps.w pitek mnie nie bdzie.:D

HTML table porting to SQL: Is there anyway i can extract data from a HTML table (i
tried jsoup) and then save it http://t.co/GBu9mbYb

@prakharprasad @yashkadakia Thats not SQL. :)

#SQL #job - Correction and optimization of a Mobile Site - Los Angles area ($20 -
30/hr) - http://t.co/jXol6m35 #jobs
Maintenance
Redis est un systme trs simple. Conu au dpart comme un moteur totalement en
mmoire, il intgre petit petit plus de fonctionnalits, prsentes rapidement dans les
sections suivantes.

Performances
Un test de performances de Redis peut tre simplement effectu avec loutil redis-benchmark,
qui effectue une suite doprations de tests et retourne des statistiques de performances
pour les oprations les plus courantes. Voici un extrait des rsultats de son appel sur notre
systme :
====== LRANGE_600 (first 600 elements) ======

10000 requests completed in 2.04 seconds


50 parallel clients
3 bytes payload

keep alive: 1
0.01% <= 2 milliseconds
0.16% <= 3 milliseconds

0.99% <= 4 milliseconds


52.87% <= 5 milliseconds
95.09% <= 6 milliseconds

97.93% <= 7 milliseconds


99.05% <= 8 milliseconds

99.86% <= 9 milliseconds


99.96% <= 10 milliseconds
100.00% <= 10 milliseconds

4909.18 requests per second


====== MSET (10 keys) ======

10000 requests completed in 0.34 seconds


50 parallel clients

3 bytes payload

keep alive: 1
6.88% <= 1 milliseconds

92.90% <= 2 milliseconds

97.85% <= 3 milliseconds


99.51% <= 5 milliseconds

99.76% <= 7 milliseconds

100.00% <= 7 milliseconds


29850.75 requests per second

Comme vous pouvez le constater, chaque opration est teste et les rsultats vous
permettent dj de juger de lefficacit de Redis sur votre systme. La plupart des
oprations de Redis offrent une vitesse relativement constante mme avec une base de
donnes dont le volume augmente.
INFO et MONITOR
La commande Redis INFO donne aussi quelques indications sur le systme. Voici une partie
du rsultat sur notre systme :
# Memory

used_memory:4350456
used_memory_human:4.15M

used_memory_rss:7872512
used_memory_peak:7173840

used_memory_peak_human:6.84M

# CPU

used_cpu_sys:54.75
used_cpu_user:25.59

used_cpu_sys_children:0.03

used_cpu_user_children:0.11

Nous y voyons loccupation mmoire actuelle et le temps processeur consomm. Une


explication sur les compteurs est disponible cette adresse :
http://redis.io/commands/info.
La commande MONITOR permet de tracer toutes les commandes envoyes au serveur.
slowlog

Un journal des requtes lentes (slowlog) est aussi maintenu en mmoire par Redis. Par
requtes lentes, on entend les requtes qui dpassent le temps spcifi en microsecondes
par loption de configuration slowlog-log-slower-than. Loption slowlog-max-len permet
dindiquer un nombre maximal denregistrements conserver dans le slowlog. Vous
pouvez ensuite linterroger avec la commande slowlog, par exemple :
slowlog get
slowlog get 10
slowlog len

slowlog reset

La premire commande rcupre la liste des commandes enregistres dans le slowlog. La


suivante en retourne seulement les dix dernires (les dix plus rcentes). slowlog len retourne
le nombre dentres et slowlog reset vide le slowlog.

Persistance
Redis est par nature une base de donnes en mmoire. Un systme de persistance sur
disque y a t ajout, lequel sauvegarde ltat des bases de donnes jusquau prochain
redmarrage de Redis. Le systme par dfaut est nomm RDB, qui se base sur la prise
rgulire ou manuelle dun snapshot, nomm dump.rdb. Ce snapshot est stock sur le disque
dans le rpertoire courant de Redis (celui dans lequel il a dmarr) ou dans un rpertoire
indiqu dans le fichier de configuration si celui-ci est spcifi au dmarrage. Par exemple,
notre dump.rdb contenant nos 15 000 tweets pse un peu moins de 2 Mo.
Loption de configuration save permet dindiquer la frquence de sauvegardes RDB. Nous
pouvons linscrire dans un fichier de configuration ou la modifier avec la commande CONFIG
SET. La commande CONFIG GET retrouve la valeur actuelle. Pour notre exemple, cela donne :
redis-cli config get save

1) "save"
2) "3600 1 300 100 60 10000"

ce qui signifie : une sauvegarde doit tre faite aprs 3 600 secondes sil y a au moins une
modification de donnes, aprs 300 secondes sil y a au moins 100 modifications, et aprs
60 secondes sil y a au moins 10 000 modifications. La commande BGSAVE permet de lancer
une sauvegarde manuelle non bloquante (BG = background). Lorsque Redis redmarre, le
fichier dump.rdb est automatiquement recharg pour remplir les bases de donnes Redis.
Cette mthode de sauvegarde dinstantans peut bien sr provoquer des pertes de donnes
si le serveur est arrt brusquement : les donnes modifies depuis la dernire sauvegarde
seront perdues. Une autre mthode de persistance est disponible, nomme AOF (Append-
Only File, fichier ajout seulement), qui quivaut plus ou moins un Write-Ahead Log.
Pour activer AOF, assurez-vous que votre fichier de configuration contienne la ligne
suivante :
appendonly yes

Chaque modification de donnes sera alors ajoute au journal, lequel sera rejou au
dmarrage de Redis. Un fichier AOF sera plus volumineux quun fichier RDB, et le
dmarrage sera plus lent, mais il ny aura pas de perte de donnes. Vous pouvez amliorer
les performances dAOF grce loption de configuration appendfsync qui vous permet de
configurer plus finement les critures de journal. Les deux valeurs utiles sont reprises dans
le tableau 10-1.
Tableau 10-1. Valeurs pour appendfsync

Valeur Description
always Ajoute au fichier AOF chaque modification, plus sr mais plus intensif.
everysec Ajoute au fichier AOF chaque seconde. Relativement sr et plus lger.

Si le fichier AOF est un journal, et quil est rejou chaque dmarrage, vous devriez
maintenant vous dire que cest une option particulirement inefficace : au fur et mesure
des modifications, le fichier AOF devrait prendre une taille respectable, et le dmarrage
devrait devenir de plus en plus long. Heureusement, Redis va compacter rgulirement ce
fichier, en liminant toutes les tapes intermdiaires. Si une cl a t modifie cent fois,
seule la dernire valeur est conserve afin de reconstruire la donne la plus frache. Ce
compactage est excut automatiquement en tche de fond, mais vous pouvez aussi le
dclencher manuellement avec la commande BGREWRITEAOF.

Rplication
Un serveur Redis peut tre configur pour tre le secondaire dun autre serveur, dans une
architecture matre-esclave arborescente (un secondaire peut se baser sur un secondaire).
Pour cela, il suffit de mentionner dans le fichier de configuration :
slaveof ip port

en indiquant lIP et le port du serveur matre. Le serveur secondaire est la copie exacte du
serveur matre. Loption slave-serve-stale-data indique le comportement observer si la
connexion avec le matre est perdue. La valeur par dfaut est yes : le serveur continue
rpondre avec des donnes potentiellement dsynchronises. Si loption vaut no, une
requte sur le serveur secondaire retourne une erreur SYNC with master in progress .
La commande SLAVEOF permet de dterminer si le serveur est un secondaire.
Loption slave-read-only, par dfaut yes, indique si les critures sont interdites sur le
secondaire. crire sur un Redis secondaire na dintrt que pour des donnes phmres :
il ny a pas de synchronisation vers le serveur matre et les donnes pourront donc tre
crases par des modifications effectues sur le matre.

Redis-sentinel et Redis Cluster


Redis-sentinel (http://redis.io/topics/sentinel) est un outil disponible depuis longtemp en
bta, mais utilis trs souvent en production parce que parfaitement stable. Il sagit dun
outil de monitoring et de gestion de haute disponibilit. Il permet, conjointement loption
de configuration slave_priority, de promouvoir automatiquement un secondaire en matre si
ce dernier est indisponible.
La version 3 de Redis intgre redis-sentinel et lamliore en un systme de sharding
intgr qui permet de transformer Redis en vritable moteur distribu.
Redis Cluster (http://redis.io/topics/cluster-tutorial) est un systme dcentralis o les
nuds communiquent laide un canal TCP supplmentaire. Les donnes sont shardes
automatiquement par Redis en utilisant la technique des vnodes, nommes ici des hash
slots. Le nombre de slots est fix 16 384, et le placement de la cl est simplement
effectu en calculant le modulo 16 384 du hash de la cl.
La rplication est assure selon un modle matre-secondaire. Si vous voulez crer un
cluster de trois shards, vous ajoutez trois machines pour accueillir les rplicas. Vous devez
avoir plus de deux matres, car le basculement automatique se fait par quorum : il faut
donc tre au moins deux pour prendre la dcision.
Les ajouts la configuration de Redis pour Redis Cluster sont les suivants :
cluster-enabled yes
cluster-config-file nodes.conf

cluster-node-timeout 5000

appendonly yes

Avec cluster-enabled, on indique bien entendu que Redis est en cluster. On dfinit un fichier
de configuration du cluster qui est cr et aliment automatiquement par Redis pour
maintenir les informations de ltat du cluster.
La valeur cluster-node-timeout configure en millisecondes combien de temps les autres
masters vont attendre avant de considrer quun nud est tomb sils narrivent pas le
joindre.
Nous avons mentionn loption appendonly que nous connaissons dj pour indiquer que les
nuds de Redis Cluster doivent fonctionner en appendonly.
Lorsque les nuds sont dmarrs, depuis nimporte quelle machine, vous devez lancer un
script Ruby disponible dans le rpertoire des binaires de Redis, et qui sappelle redis-
trib.rb. Ce script va initialiser le cluster. Vous navez rien dautre faire. Voici un exemple
avec six machines installes en pseudo distribu sur la mme machine en coute sur les
ports TCP 7000-7005 :
./redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 \

127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005

Toute la question de Redis Cluster est de trouver une bibliothque client qui le supporte.
Allez sur http://redis.io/topics/cluster-tutorial pour voir ltat du dveloppement
communutaire des clients. Vous y trouvez notamment la rfrence au client dvelopp par
StackExchange pour .NET. StackExchange est un site important et trs connu, qui utilise
beaucoup Redis comme cache. Leur environnement est plutt Microsoft et cest pour cette
raison quils ont dvelopp un client .NET.
Idalement, il sagit de trouver un smart client pour votre langage. Redis est capable de
rediriger la commande sur le nud qui doit hberger la cl que vous voulez crire, mais
cela ncessite un hop sur un nud et peut-tre ensuite un hop supplmentaire sur le nud
cible.
Par exemple :
redis 127.0.0.1:7000> set macle mavaleur
-> Redirected to slot [11182] located at 127.0.0.1:7002
OK

Conclusion
Redis est un merveilleux petit outil, qui devient de plus en plus intressant avec le temps.
Lintelligence de sa conception, llgance et la simplicit de son dveloppement et de ses
amliorations au fil des versions, en font un moteur de donnes trs attractif. Nous vous le
conseillons vivement.
11
Cassandra

Cassandra est un moteur de base de donnes dvelopp lorigine par Facebook par
Avinash Lakshman, lun des dveloppeurs de Dynamo dAmazon, pass depuis chez
Facebook, et Prashant Malik. Le code en a t libr en 2008.

Caractristiques du moteur
Cassandra est un moteur de bases de donnes orient colonnes. Il sinspire donc du
modle BigTable de Google, mais emprunte galement des caractristiques Dynamo
dAmazon. Une fois de plus, nous retrouvons les deux grands fondateurs du mouvement
NoSQL. Les fonctionnalits de Cassandra sont assez compltes et son architecture est
intressante. En effet, cette dernire est dcentralise comme celle de Dynamo.
Contrairement HBase, elle ne se base pas sur un systme de fichiers distribu. Cassandra
est donc un moteur autosuffisant.

Modle de donnes
Dans Cassandra, les donnes sont regroupes en familles de colonnes. Une famille de
colonnes (column family) est plus ou moins lquivalent dune table dans le modle
relationnel, la diffrence que son schma nest pas fix lavance : chaque ligne peut
avoir un nombre diffrent de colonnes. Chaque famille de colonnes est stocke dans son
propre fichier sur le disque.
Une colonne est dfinie par son nom, qui nest pas forcment une chane de caractres : le
nom de colonne peut tre dun autre type, comme un entier ou un UUID, ce qui est
pratique pour crer manuellement des index secondaires. La colonne contient une valeur et
un horodatage (timestamp).
La version 2 de Cassandra, sortie en 2014, a un peu dissimul ce stockage interne. Au
ressenti, un dveloppeur Cassandra se retrouve comme devant des tables de SGBDR.
Nous allons en parler.

Stockage
Les critures de donnes sont dabord effectues squentiellement dans un WAL, nomm
le commit log. Elles sont ensuite envoyes aux nuds en fonction du type dcriture,
comme nous le verrons dans la section suivante consacre la mise en uvre de
Cassandra. Chaque nud crit la donne dans son commit log et lajoute en mmoire dans
une memtable. La memtable est lquivalent dun buffer, cest une reprsentation en
mmoire de paires cl-valeur de donnes dune famille de colonnes. Chaque famille de
colonnes a sa memtable. Elle est crite sur le disque aprs un certain dlai, par exemple si
la mmoire est sature ou si un nombre dfini de cls a t ajout. Le fichier enregistr sur
le disque sappelle une SSTable (Sorted Strings Table). Un filtre de Bloom est aussi
maintenu, qui est une structure permettant de dterminer si une cl est prsente ou non
dans la SSTable en utilisant un algorithme bas sur les probabilits. Cest une faon
lgante damliorer les performances daccs aux donnes. Chaque fois quune memtable
est sauvegarde, elle scrit dans une nouvelle SSTable. Il peut donc y avoir plusieurs
SSTables pour la mme famille de colonnes et les SSTables sont immutables : il y aura
toujours cration de nouvelles SSTables, jamais de modification dun SSTable existante.
Rgulirement, un compactage cre une nouvelle SSTable partir des existantes.

Mise en uvre

Installation
Vous pouvez obtenir Cassandra de deux manires : depuis Apache, ou depuis les dpts de
Datastax, une socit qui sest dveloppe autour de ce moteur. Datastax dispose dune
version community que nous allons utiliser ici.
Un dpt pour Debian (donc compatible avec Ubuntu) est disponible en ligne. Vous
trouverez les explications ncessaires ladresse suivante :
http://www.datastax.com/documentation/cassandra/2.0/cassandra/install/installDeb_t.html.
Nous ajoutons les dpts notre fichier /etc/apt/sources.list :
deb http://debian.datastax.com/community stable main

Avant linstallation, nous importons la cl publique gpg (GNU Privacy Guard, lquivalent
libre de PGP) qui permettra de vrifier la signature du paquet afin de garantir son
authenticit :
curl -L http://debian.datastax.com/debian/repo_key | sudo apt-key add -

Ensuite, nous installons Cassandra comme tout autre paquet :


sudo apt-get update

sudo apt-get install dsc20=2.0.11-1 cassandra=2.0.11

Comme vous le voyez, nous indiquons la version, ce qui peut tre utile pour viter ensuite
lcrasement automatique par une nouvelle version lors dun upgrade avec apt-get (dsc
signifie DataStax Community).
Linstallation du paquet dmarre le dmon Cassandra. Nous pouvons nous en assurer en le
cherchant dans les processus du systme, ou en vrifiant sil coute sur son port TCP par
dfaut, le port 9160.
netstat -lt | grep 9160

Afin de permettre laccs au serveur depuis une machine distante, nous changeons la
configuration de Cassandra situe dans le fichier /etc/cassandra/cassandra.yaml, en modifiant
la ligne suivante :
rpc_address: localhost

en :
rpc_address: 0.0.0.0

Puis nous redmarrons :


sudo service cassandra restart

Configuration
Le fichier de configuration de Cassandra est situ sur notre systme
/etc/cassandra/cassandra.yaml. Le tableau 11-1 liste quelques lments pour parcourir les
possibilits de Cassandra. Nous avons dj vu le paramtre snitch dans le chapitre 3 ddi
la distribution des donnes.
Tableau 11-1. lments de configuration

Option de
Description
configuration
cluster_name Nom logique du cluster, permet didentifier les nuds faisant partie dun mme cluster.
La valeur de token pour ce nud dans lanneau, cest--dire une valeur numrique de
crc32 qui sera la range de ce nud dans lanneau (voir la section sur le hachage
initial_token consistant du chapitre 3, page 78). Cette option est dprcie et ne doit tre utilise que
sur des machines qui vont joindre un cluster existant. Pour les nouveaux clusters, voyez
loption suivante.
Le nombre de vnodes hberger sur ce nud. Le dfaut est 1 pour dsactiver la
num_tokens fonctionnalit de vnodes par souci de compatibilit. Mettez 256 pour utiliser les vnodes,
cest la valeur recommande.
Authenticator Permet dindiquer une classe Java pour authentifier les connexions au serveur.
Authority Permet dindiquer une classe Java pour implmenter les permissions.
Taille du cache de cls. Une zone de mmoire ddie la conservation des cls. Trs
key_cache_size_in_mb
intressant pour amliorer les performances. Le stockage des seules cls en mmoire est
compact. Le cache peut tre sauvegard rgulirement sur le disque pour tre recharg au
dmarrage de Cassandra.
Taille du cache de lignes. Moins intressant que le cache de cls, car sa taille en mmoire
row_cache_size_in_mb est plus importante, et sa maintenance est plus lourde si les valeurs sont rgulirement
mises jour.

LAPI Thrift
Historiquement, laccs Cassandra tait ralis via Thrift. Loutil en ligne de commande
cassandra-cli tait est toujours car il existe pour compatibilit un moyen interactif pour
nous connecter au serveur :
cassandra-cli --host localhost --port 9160

Et cest loutil que nous avions montr dans la premire dition de ce livre. Depuis, la
rvolution Cassandra 2 est passe. Cassandra 2 a dprci lAPI Thrift au profit de CQL.
CQL est un langage dclaratif semblable SQL, qui utilise un protocole binaire de type
RPC pour communiquer avec le serveur. De ce fait, les performances sont meilleures
quavec lAPI Thrift (voyez par exemple ceci
http://www.datastax.com/dev/blog/cassandra-2-1-now-over-50-faster), tout en offrant un
langage facile manipuler et familier tout dveloppeur ayant dj fait du SQL, cest--
dire tout dveloppeur
Juste pour savoir de quoi nous parlons, voici un exemple basique dajout de donnes
laide de commandes de lAPI Thrift :
assume articles keys as utf8;
set articles[1][auteur_prenom] = Annie;

set articles[1][auteur_nom] = Brizard;

set articles[1][auteur_email] = annie.brizard@cocomail.com;


set articles[1][titre] = pourquoi les lphants ont-ils de grandes oreilles ?;

Vous voyez le genre. Passons donc CQL, qui la remplac.

CQL 2 et 3
Cassandra implmente donc un langage de requte proche du SQL, nomm CQL
(Cassandra Query Language). Vous le voyez dans le titre de cette section, il y a eu deux
versions importantes de CQL. Pourquoi parler dune ancienne version ? pour illuster un
changement important.
CQL 2 a t dfini comme un ajout lAPI Thrift. Il offrait moins de fonctionnalits et se
basait conceptuellement sur Thrift. Par exemple, vous pouviez en CQL 2 faire ceci :
CREATE COLUMNFAMILY articles (

KEY bigint PRIMARY KEY,


auteur:prenom varchar,
auteur:nom varchar

);

Puis ceci :
INSERT INTO articles (KEY, auteur:prenom, auteur:nom, auteur:email)
VALUES (1, Frank, Lavue, frank.lavue@cocomail.com);

Vous voyez ? Nous insrons le contenu dune colonne, auteur:email, que nous navons pas
dfini dans le CREATE COLUMNFAMILY. CQL 2 nest quune surcouche.
Cela nest plus possible en CQL 3. Pour travailler avec une famille de colonnes, elle doit
avoir avoir t cre, avec le bon nombre de colonnes et mme le bon type de donnes. Au
lieu dtre juste un sucre de syntaxe, CQL 3 est une couche dabstraction qui cache la
structure interne du stockage Cassandra, tel point que voyons un exemple diffrent :
CREATE TABLE commentaires (

article_id bigint,
date_commentaire timestamp,

auteur varchar,

contenu text,
PRIMARY KEY (article_id, date_commentaire)

);

Ici, nous voulons stocker des commentaires posts sur un article de blog, rfrenc par un
article_id. Quelles sont les diffrences avec la dclaration prcdente ? Dabord, nous
disons CREATE TABLE au lieu de CREATE COLUMNFAMILY. Ce sont des synonymes mais on se
rapproche du ressenti dun SGBDR. Ensuite, nous indiquons un nom pour chaque
colonne, l o nous avions indiqu auparavant KEY pour la row key. Ensuite, nous
dfinissons une cl primaire composite ! On la vu, Cassandra stocke chaque ligne par
rapport une row key. Cette row key peut-elle tre composite ? Non, et ce que nous
venons de dclarer en CQL 3 sera stock de faon toute particulire dans Cassandra, sous
forme de ce qui est appel une wide row. En ralit, chaque commentaire sur le mme
article sera stock dans la mme ligne, et la row key de cette ligne sera larticle_id. Voici
un exemple de stockage interne de deux commentaires sur le mme article (larticle 1)
posts le 1er janvier 2015 et le 10 janvier 2015. Nous reprsentons ici le contenu dune
seule ligne dans Cassandra, en montrant les types de donnes de faon logique, et non pas
tels quils sont physiquement stocks :
Cl COLONNE VALEUR

1: 2015-01-01:

2015-01-01:auteur Jean Posteur


2015-01-01:contenu Tout fait daccord

2015-01-10:
2015-01-10:auteur Anne Lafleur
2015-01-10:contenu Bon article

En fait, chaque insertion dans cette table sur le mme article_id va gnrer une cration,
non pas dune nouvelle ligne dans la table, mais de trois nouvelles colonnes sur la ligne
identifie par article_id. Cela va permettre de conserver tous les commentaires sur le mme
article sur le mme nud Cassandra pour un accs plus rapide. Cassandra compacte ces
donnes, donc limpact en stockage sera peu important, et CQL 3 compose et dcompose
la ligne lorsquil la manipule.

Gestion de la cohrence
Dans Cassandra, la cohrence des critures et des lectures est configurable par instruction.
Les options de cohrence sont rsumes dans le tableau 11-2.
Tableau 11-2. Modes de respect de la cohrence

Niveau Description

ANY
Lcriture doit tre faite sur un nud au moins, mme si cest un hinted handoff. Disponible en
criture uniquement.

ONE
Lcriture ou la lecture doit tre ralise sur un nud au moins. Lcriture doit tre inscrite dans le
commit log et la memtable.
Lcriture ou la lecture doit tre au moins effectue sur le quorum des rplicas de cette donne,
QUORUM cest--dire la moiti des rplicas plus un. Lcriture doit tre inscrite dans le commit log et la
memtable de ces rplicas.
Lcriture ou la lecture doit tre faite au moins sur le quorum des rplicas de cette donne, prsents
LOCAL_QUORUM dans le data center local. Cela permet de saffranchir des dlais dus la prsence de rplicas sur
dautres data centers. Lcriture doit tre inscrite dans le commit log et la memtable des rplicas.

EACH_QUORUM
Lcriture ou la lecture doit tre au moins ralise sur un quorum des rplicas de cette donne,
prsents dans chaque data center.
ALL Lcriture ou la lecture doit tre effectue sur tous les rplicas.

Comme vous le voyez, nous ne sommes pas ici dans une cohrence finale obligatoire,
mais nous pouvons dcider au cas par cas. Le niveau par dfaut est ONE. Voici comment
modifier le niveau de cohrence pour la session en CQL :
CONSISTENCY QUORUM;

Au niveau des lectures, Cassandra dispose dune fonctionnalit de Read Repair


automatique. Une lecture directe entrane une lecture asynchrone en tche de fond sur les
rplicas qui ne sont pas affects par la demande de lecture, afin de dtecter ventuellement
des changements et de les rpercuter sur les autres rplicas.
Hinted handoff
La fonctionnalit hinted handoff permet de synchroniser un nud qui est indisponible pour une petite priode de
temps. Une criture est toujours envoye tous les rplicas. Si un rplica nest pas disponible, les autres rplicas
vont garder une information indiquant quune criture est en attente pour ce nud, et lorsquil est de nouveau
disponible, ils lanceront lcriture.

Programmation client
Dans ldition prcdente de cet ouvrage, nous avions utilis le client Python pycassa
(https://github.com/pycassa/pycassa). Cette bibliothque utilise le protocole Thrift. Si vous
tes en Cassandra 2, elle est dprcie. Datastax, la socit qui distribue et concourt au
dveloppement de Cassandra, a conu un client Python qui utilise le protocole CQL
(https://github.com/datastax/python-driver). Nous allons donc lutiliser dornavant. Si
vous souhaitez travailler plutt en objets quen CQL, un ORM (outil de mapping
relationnel-objet) pour Python nomm cqlengine (https://github.com/cqlengine/cqlengine)
offre une couche dabstraction supplmentaire. Nous allons vous montrer comment utiliser
les deux.
Dabord, pour compiler au mieux le pilote, nous installons des bibliothques sur Ubuntu :
sudo apt-get install libev4 libev-dev

Elles vont permettre la compilation de cassandra.io.libevwrapper, laquelle est lextension


qui va travailler directement avec lalgorithme de hachage utilis par Cassandra et
permettre de diriger les appels vers le bon nud. Sans cela, le client fonctionnera mais
sera plus lent, car il appellera un nud qui redirigera la requte, au lieu daller directement
au bon endroit.
Puis nous installons le pilote et sqlengine :
~/python_env/nosql/bin/pip install cassandra-driver

Nous allons utiliser notre traditionnel exemple Passerelles et ajouter un article, puis le
rcuprer.
#! /usr/bin/python

# -*- coding: utf8 -*-


import uuid

import datetime

from cqlengine import columns


from cqlengine.models import Model

class Article(Model):

read_repair_chance = 0.05 # optional - defaults to 0.1


article_id = columns.UUID(primary_key=True, default=uuid.uuid4)
auteur_prenom = columns.Text(required=True)

auteur_nom = columns.Text(required=True, index=True)


date = columns.DateTime()

titre = columns.Text(required=True)
article = columns.Text(required=True)
from cqlengine import connection

connection.setup([192.168.0.16], passerelles)

from cqlengine.management import create_keyspace


create_keyspace(passerelles, SimpleStrategy, 1)

from cqlengine.management import sync_table

sync_table(Article)
ar = Article.create(auteur_prenom=Annie, auteur_nom=Dakota, date=datetime.datetime.now(),
titre=Les lphants ont-ils de grande oreilles?, article=une longue histoire )

Article.objects.count()
q = Article.objects(auteur_nom = Dakota)
for instance in q:

print instance.titre

Nous crons dabord une classe dont les proprits correspondent aux types Cassandra.
Nous ouvrons ensuite une connexion avec cqlengine.
Puis nous utilisons la mthode create_keyspace pour crer un keyspace, donc une base de
donnes. Nous utilisons alors la mthode sync_table pour crer la table, et nous insrons
une ligne.
Nous effectuons finalement une recherche sur une colonne indexe avec la mthode
Article.objects().

Nodetool
Lutilitaire nodetool permet deffectuer des oprations de maintenance ou dobtenir des
informations sur le nud Cassandra.
Par exemple, la commande :
nodetool ring

retourne la liste des machines dans lanneau. Pour notre exemple, il ny en a quune, voici
le rsultat :

Figure 11-1
Rsultat de nodetool ring

Nous voyons les informations de data center (DC), de rack et le token, telles que nous les
avons configures.
La commande :
nodetool cfstats
retourne des statistiques sur les familles de colonnes. Voici un extrait du rsultat pour la
famille de colonnes passerelles :
Keyspace: passerelles

Read Count: 9
Read Latency: 4.22 ms.

Write Count: 11
Write Latency: 0.3235454545454546 ms.

Pending Tasks: 0

Column Family: articles

SSTable count: 1
Space used (live): 4798

Space used (total): 4798

Number of Keys (estimate): 128


Memtable Columns Count: 10
Memtable Data Size: 275

Memtable Switch Count: 1


Read Count: 9

Read Latency: 4,220 ms.


Write Count: 11
Write Latency: 0,324 ms.

Pending Tasks: 0
Bloom Filter False Postives: 0
Bloom Filter False Ratio: 0,00000

Bloom Filter Space Used: 24


Compacted row minimum size: 87
Compacted row maximum size: 258

Compacted row mean size: 192

Ces informations sont prcieuses pour juger des performances de Cassandra.


Lappel suivant retire un nud de lanneau :
nodetool disablegossip

Pour le faire revivre, nous lanons ensuite la commande suivante :


nodetool enablegossip

Puis nous vrifions que le nud communique avec les autres :


nodetool netstats

Conclusion
Cassandra est un des moteurs les plus complets et les mieux btis, il vous permet dallier
les avantages dun moteur orient colonnes avec larchitecture dcentralise et les
capacits de monte en charge automatique de Dynamo. Cest un choix intressant pour
les environnements critiques.
12
Les autres bases de donnes de la
mouvance NoSQL

Nous vous avons prsent les moteurs de bases de donnes NoSQL les plus importants. Il
en existe beaucoup dautres, sinspirant plus ou moins des mmes techniques, mais ils sont
pour la plupart moins aboutis et moins utiliss que ceux que nous avons vus.
Dans ce chapitre, nous souhaitons vous prsenter deux types doutils trs intressants quil
est galement possible de classer dans la catgorie des moteurs NoSQL : le moteur de
recherche ElasticSearch et le moteur orient graphes, Neo4j.

ElasticSearch
ElasticSearch nest pas un systme de gestion de bases de donnes. Il sagit dun moteur
de recherche plein texte indexation automatique, dvelopp par Shay Banon et bas sur
Lucene. Il est principalement utilis pour alimenter la recherche plein texte sur des sites
web. Cet outil est donc semblable au moteur de recherche de Google, par exemple.
Lucene
Lucene est un clbre moteur de recherche plein texte de la fondation Apache. Cest une application Java
dveloppe par Doug Cutting, lequel crera plus tard Hadoop, et qui offre dexcellentes performances.

ElasticSearch constitue une surcouche de Lucene, dont il reprend les fonctionnalits de


recherche. Il permet de rpartir le travail sur plusieurs machines et offre galement une
interface REST afin daccder trs simplement ses fonctionnalits. Grce cette
interface REST, il est possible denvoyer des documents JSON indexer et deffectuer des
recherches. Il sagit donc dun moteur de recherche orient documents, ce qui le rapproche
beaucoup du mouvement NoSQL. Passons maintenant la pratique.
Pour commencer, rendez-vous sur le site dElasticSearch pour tlcharger le moteur de
recherche : http://www.elasticsearch.org/download/.
En cliquant sur le numro de version que vous souhaitez, vous y trouverez un paquet
Debian (extension .deb), que vous devez rcuprer et installer. Nous avons pour notre part
rcupr le lien du paquet et nous lavons tlcharg avec wget :
wget https://github.com/downloads/elasticsearch/elasticsearch/elasticsearch-1.4.4.deb

Puis nous installons le paquet avec dpkg . la fin de linstallation, le dmon est
automatiquement dmarr.
sudo dpkg -i elasticsearch-1.4.4.deb
ElasticSearch peut ensuite tre arrt et lanc comme un service :
sudo service elasticsearch stop
sudo service elasticsearch start

Sur notre systme, le fichier de configuration est /etc/elasticsearch/elasticsearch.yml. Nous


pouvons y paramtrer les informations du cluster, comme son nom ainsi que les attributs
du nud qui pourront tre utiliss comme paramtres pour le sharding des donnes
dindexation. La topologie est autant que possible autoconfigure, mais nous pouvons
intervenir manuellement dans ce fichier pour dterminer quelles sont les responsabilits du
nud, entre nud matre et nud de donnes.

Mise en uvre
ElasticSearch rpartit ses index de la mme manire que les moteurs NoSQL distribus
que nous avons tudis prcdemment, cest--dire en effectuant un sharding et une
rplication des donnes. Pour son interface REST, ElasticSearch coute par dfaut sur
toutes les interfaces, et sur le port 9200. Si nous appelons linterface REST cette adresse,
nous obtenons :
{
status : 200,

name : Mentus,
version : {
number : 1.2.0,

build_hash : c82387f290c21505f781c695f365d0ef4098b272,
build_timestamp : 2014-05-22T12:49:13Z,
build_snapshot : false,

lucene_version : 4.8
},

tagline : You Know, for Search


}

Grce un appel REST, nous allons directement crer un index nomm passerelles. On
peut considrer ici que lindex quivaut plus ou moins une base de donnes :
curl -X PUT http://localhost:9200/passerelles

Nous recevons cette notification :


{ok:true,acknowledged:true}

Nous stockons ensuite un document :


curl -X PUT http://localhost:9200/passerelles/articles/1 -d

auteur:
{

prnom:Annie,

nom:Brizard,
e-mail:annie.brizard@cocomail.com

},
titre:pourquoi les lphants ont-ils de grandes oreilles ?

Mapping des types


Chaque lment du document est mapp un type de donne. ElasticSearch reconnat les types de donnes JSON
de faon mieux qualifier la donne dans la recherche. Ce mapping peut aussi tre effectu manuellement, laide
dune API de mapping. Les types sont reprsents par des classes de Mapper, qui senrichissent au fil du temps. Par
exemple, il existe des classes de mapping pour les points et les formes gospatiales, qui utilisent des bibliothques
gospatiales pour Java. Le mapping permet de dterminer le comportement de lindexation par rapport aux
diffrents champs dun document.

Nous avons cr le document 1 dans lindex passerelles. Comme vous lavez sans doute
remarqu, il existe un niveau intermdiaire appel type, dont la valeur est articles pour
notre exemple. Le type est cr automatiquement lorsque vous ajoutez un document, il
quivaut plus ou moins une table. Nous obtenons la confirmation suivante :
{ok:true,_index:passerelles,_type:articles,_id:1,_version:1}

On voit ici quun numro de version est galement attribu au document, tout ceci
ressemble trs fortement un moteur NoSQL. Dailleurs, comme on peut le faire dans un
moteur tel que CouchDB, il nous suffit dutiliser un GET pour retrouver notre document :
curl -i http://localhost:9200/passerelles/articles/1

et nous obtenons :
HTTP/1.1 200 OK

Content-Type: application/json; charset=UTF-8


Content-Length: 259

{_index:passerelles,_type:articles,_id:1,_version:1,exists:true, _
source :
{

auteur:
{
prnom:Annie,

nom:Brizard,
e-mail:annie.brizard@cocomail.com

},

titre:pourquoi les lphants ont-ils de grandes oreilles ?


}}

La prsence dun numro de version est utile pour grer un verrouillage optimiste, comme
dans CouchDB.
Dans la mesure o il sagit dun moteur dindexation, effectuons donc une recherche. Le
plus simple est denvoyer une chane de recherche dans lURL. Dans lexemple suivant,
nous voulons trouver les articles dont le titre contient le mot oreilles :
curl -i http://localhost:9200/passerelles/_search?q=titre:oreilles

Nous obtenons :
HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8

Content-Length: 384

{took:175,timed_out:false,_shards:{total:5,successful:5,failed:0},hits:{
total:1,max_score:0.095891505,hits:[{_index:passerelles,_

type:articles,_id:1,_score:0.095891505, _source :
{

auteur:
{
prnom:Annie,

nom:Brizard,

e-mail:annie.brizard@cocomail.com
},

titre:pourquoi les lphants ont-ils de grandes oreilles ?

}}]}}

Si les donnes sont shardes, ElasticSearch lancera la recherche sur tous les shards et
renverra le rsultat regroup.

Plug-ins et rivires
Les fonctionnalits dElasticSearch peuvent tre enrichies laide de plug-ins, et
notamment ce que lon appelle des rivires . Ces dernires sont des connecteurs des
sources de donnes qui permettent de dverser au fil de leau les nouvelles donnes
indexer dans ElasticSearch. Des rivires existent pour diffrents types de sources, bases de
donnes NoSQL ou SQL, sites comme Wikipdia ou rseaux sociaux tels que Twitter, etc.
Elles sont dveloppes par lquipe dElasticSearch ou par des dveloppeurs tiers. Des
rivires existent notamment pour MongoDB et CouchDB. Dans ce dernier, la
fonctionnalit de suivi des changements, dont nous navons pas encore parl, permet
denvoyer les donnes vers ElasticSearch. Voyons tout cela travers un exemple.
Rivire CouchDB

CouchDB offre une fonctionnalit de suivi de changements travers lAPI _changes. Au


plus simple, en appelant _changes sur une base de donnes, nous obtenons la liste des
modifications qui y ont t apportes. Essayons sur notre base passerelles :
curl http://nosql-server:5984/passerelles/_changes

Nous obtenons ceci :


{results:[

{seq:2,id:id_article_1,changes:[{rev:2-f6c92fbe3b7579f0f6819e1c85db3eaa}],
deleted:true},

{seq:4,id:1,changes:[{rev:2-1a97e3eb387fd93cf6e1abb2a1aed56b}]},

{seq:6,id:a642aa5b272c49d72aab7aef26226508,changes:[{rev:2-5c8ec9a6b2973061
2c2eba48ea845943}],deleted:true},

{seq:7,id:a642aa5b272c49d72aab7aef26415ce4,changes:[{rev:1-a0e81b6cc21cb1e5

52dad87ec4c41f49}]},
{seq:8,id:a642aa5b272c49d72aab7aef266097d5,changes:[{rev:1-a0e81b6cc21cb1e5

52dad87ec4c41f49}]},

{seq:9,id:a642aa5b272c49d72aab7aef267e7951,changes:[{rev:1-a0e81b6cc21cb1e5
52dad87ec4c41f49}]},

{seq:12,id:2,changes:[{rev:3-7379b9e515b161226c6559d90c4dc49f}],deleted:
true},

{seq:13,id:_design/
python,changes:[{rev:1-c40cae63adc999b7ed184e6324da50bd}]}

],
last_seq:13}

Saffiche donc la liste des modifications qui contient les cls, les identifiants de versions et
les types de changements. Nous obtenons aussi des numros de squences, qui
reprsentent lordre des changements, ainsi que le dernier numro de squence (13) pour
terminer. Dans notre application, il suffit de stocker ce dernier numro et de lindiquer de
la manire suivante au prochain appel :
curl http://nosql-server:5984/passerelles/_changes?since=13

pour rcuprer les modifications effectues aprs le numro de squence 13, et ainsi de
suite.
Le suivi des changements peut aussi tre appel en long polling, cest--dire en
maintenant une connexion HTTP jusqu ce quun rsultat soit obtenu. La commande
suivante :
curl http://nosql-server:5984/passerelles/_changes?feed=longpoll&since=13

ne rendra la main que lorsquune modification sera apporte la base passerelles. Enfin, le
mode continu laisse la connexion ouverte et rcupre au fil de leau les modifications en
temps rel :
curl http://localhost:5984/passerelles/_changes?feed=continuous&since=13

Configuration et utilisation de la rivire

Comme mentionn prcdemment, une rivire est un plug-in dElasticSearch. Il convient


donc de linstaller laide de la commande plugin situe dans le rpertoire bin
dElasticSearch :
/usr/share/elasticsearch/bin/plugin -install elasticsearch/

elasticsearch-river-couchdb/1.1.0

Ensuite, pour configurer la rivire, nous excutons simplement la commande REST


suivante, qui envoie les informations de configuration dans son JSON.
curl -XPUT localhost:9200/_river/passerelles/_meta -d {

type : couchdb,

couchdb : {
host : localhost,

port : 5984,

db : passerelles,

filter : null
},

index : {

index : passerelles,
type : passerelles,

bulk_size : 100,

bulk_timeout : 10ms
}

Nous indiquons ici les informations permettant ElasticSearch de se connecter


CouchDB et de rcuprer les donnes travers le suivi de changement, pour les indexer en
temps rel dans son index passerelles.
Journal dElasticSearch
Si vous rencontrez des problmes, consultez le log dElasticSearch afin dobtenir des informations dtailles. Son
emplacement est dfini dans le fichier de configuration logging.yml (dans /etc/elasticsearch pour notre
configuration). Sur notre installation Ubuntu, il se trouve dans /var/log/elasticsearch.

Pour effectuer un test, nous ajoutons ensuite un document dans CouchDB :


curl -X PUT http://localhost:5984/passerelles/2 -d

auteur:
{
prnom:Jean,

nom:Crou,
e-mail:jcrou@cocomail.com
},

titre:chroniques du quotidien
}

Puis nous effectuons la recherche dans ElasticSearch :


curl -i http://localhost:9200/passerelles/_search?q=titre:quotidien

Nous obtenons :
HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8

Content-Length: 365

{took:51,timed_out:false,_shards:{total:5,successful:5,failed:0},hits:{
total:1,max_score:0.5,hits:[{_index:passerelles,_type:passerelles,_

id:2,_score:0.5, _source: {_rev:1-bb2ef2e7d8366889c36408ae44bb0a91,_

id:2,titre:chroniques du quotidien,auteur:{prnom:Jean,e-mail:jcrou@
cocomail.com,nom:Crou}}}]}}

Les facettes
Les facettes reprsentent lune des fonctionnalits majeures dElasticSearch. En plus de
retourner un rsultat de recherche, ce dernier peut galement retourner des informations
agrges sur ces rsultats, par exemple un compte doccurrences, un histogramme de
dates, etc. Les facettes disponibles sont documentes ladresse suivante :
http://www.elasticsearch.org/guide/reference/api/search/facets/index.html. Reprenons
notre exemple dindex passerelles qui intgre la base passerelles de CouchDB. Nous allons
analyser les e-mails pour dterminer la frquence dapparition dutilisateurs et de
domaines, laide de la requte suivante :
curl -X POST http://localhost:9200/passerelles/_search?pretty=true -d
{
query : {

match_all : { }
},

facets : {
e-mails : {
terms : {

field : e-mail

}
}

Nous demandons ElasticSearch de nous retourner toutes les occurrences darticles, et


dajouter un calcul de facette que nous nommons e-mails, en utilisant la facette terms. Le
rsultat fragmentaire est le suivant (nous navons conserv que la partie facette) :
facets : {
e-mails : {

_type : terms,
missing : 1,
total : 4,

other : 0,
terms : [ {
term : cocomail.com,

count : 3
}, {
term : annie.brizard,

count : 2
}, {

term : jcrou,
count : 1

} ]

}
}

Nous voyons quun document ne contient pas de champ e-mail (il est indiqu par missing).
Il y a donc trois articles qui sont analyss. On trouve trois fois cocomail.com, deux fois
annie.brizard et une fois jcrou.

Les bases de donnes orientes graphes


Le concept des bases de donnes orientes graphes existait dj avant linvention du
modle relationnel. Les implmentations modernes sont performantes et intressantes pour
certains cas dutilisation, qui correspondent des parcours darbres la recherche de
relations significatives travers les diffrents niveaux. Par exemple, dcouvrir les amis
des amis dun utilisateur qui habitent dans la mme ville, calculer un trajet dun point vers
un autre selon des critres de temps ou de distance, reprsenter la traabilit de produits ou
de flux financiers, etc.

Neo4j
Neo4j est lune des meilleures bases de donnes oriente graphes. Bien quelle soit
dveloppe en Java, elle offre dexcellentes performances et permet de traiter rapidement
de grandes quantits de relations.
Nous allons installer Neo4j sur notre systme Ubuntu. Les paquets Debian/Ubuntu sont
disponibles ladresse suivante : http://debian.neo4j.org/. Il suffit dajouter le dpt dans
la liste de nos sources de paquets, en crant par exemple un fichier
/etc/apt/sources.list.d/neo4j.list qui contient cette ligne :

deb http://debian.neo4j.org/repo testing/

Nous voulons utiliser la dernire version de Neo4j, soit la 1.8 lheure o nous crivons
ces lignes. Si vous installez Neo4j en situation de production, choisissez le paquet stable,
en rdigeant vos sources comme suit :
deb http://debian.neo4j.org/repo stable/

Nous rafrachissons ensuite la liste des paquets et nous pouvons installer lune des trois
livraisons :
sudo apt-get update && sudo apt-get install neo4j-advanced

Neo4j sinstalle et dmarre en tant que service. Nous pouvons maintenant accder au
serveur web dadministration : http://localhost:7474/webadmin/. Si vous souhaitez pouvoir
accder la page dadministration depuis une machine distante, modifiez le fichier
/etc/neo4j/neo4j-server.properties et dcommentez cette ligne :

org.neo4j.server.webserver.address=0.0.0.0

Redmarrez ensuite le service :


sudo service neo4j-service restart

Linterface dadministration est assez plaisante. La figure 12-1 reprsente lcran


daccueil.
Figure 12-1
Linterface dadministration de Neo4j

Mise en uvre
La figure 12-1 montre une instance de Neo4j o nous venons de supprimer des donnes en
vidant la base de donnes. Le graphique indique le nombre de nuds, qui vient donc
subitement de chuter, cause de notre suppression.
La base de donnes Neo4j
Neo4j ne gre pas les bases de donnes multiples. Le cas dutilisation dune base de donnes oriente graphes est
spcifique, et il ny a pas vraiment de sens de crer plusieurs bases de donnes. Neo4j stocke toutes ses donnes
dans un rpertoire. Pour supprimer la base de donnes entire, il convient darrter le service, de supprimer tous les
fichiers du rpertoire (/var/lib/neo4j/data/graph.db/ pour notre configuration) et de redmarrer le service.

Nous basculons sur longlet Console et nous allons saisir quelques nuds en utilisant le
langage Cypher.
Les langages de Neo4j

Mis part les pilotes spcifiques pour les langages clients, qui permettent de manipuler les
nuds et les relations dans un mode procdural, Neo4j offre deux langages spcifiques :
Cypher et Gremlin. Cypher est un langage dclaratif inspir du SQL, qui permet
dexprimer une requte complexe de faon lgante et compacte. Gremlin, quant lui, est
un langage de script bas sur Groovy (un langage pour la plate-forme Java dont la syntaxe
sinspire de langages de script comme Python et Ruby). Il permet denvoyer des scripts
qui seront excuts du ct serveur travers linterface REST de Neo4j. Nous allons
utiliser ici des commandes Cypher. Ces dernires peuvent galement tre lances en ligne
de commande avec linvite neo4j-shell.
Tout dabord, nous crons un nud :
CREATE n = {nom : Milou, ville : Paris};

Le premier nud porte le numro 1, comme nous pouvons le vrifier dans linterface
dadministration de Neo4j, onglet Data browser, en saisissant simplement 1 dans le
champ de saisie et en cliquant sur la loupe. Le rsultat est affich sur la copie dcran de la
figure 12-2.

Figure 12-2
Longlet Data browser de linterface dadministration de Neo4j

Nous pouvons bien sr obtenir la mme chose en Cypher :


START n=node(1) RETURN n;

qui retourne :
==> +------------------------------------+
==> | n |

==> +------------------------------------+
==> | Node[1]{nom:Milou,ville:Paris} |
==> +------------------------------------+
==> 1 row

==> 0 ms

Nous allons maintenant ajouter un deuxime nud et une relation dans la mme
commande :
START Milou = node(1)

CREATE
Tintin = { nom: Tintin, ville: Paris },

Milou-[r:AMI]->Tintin

RETURN
Tintin;

ce qui retourne :
==> +-------------------------------------+

==> | Tintin |

==> +-------------------------------------+
==> | Node[2]{nom:Tintin,ville:Paris} |

==> +-------------------------------------+
==> 1 row

==> Nodes created: 1


==> Relationships created: 1

==> Properties set: 2


==> 42 ms
==>

laide de la commande START, nous avons indiqu le point de dpart de notre pattern,
cest--dire de notre instruction. Nous avons ensuite cr un nud et une relation que nous
avons nomme AMI. Ajoutons encore quelques nuds :
START Milou = node(1), Tintin = node(2)
CREATE

Haddock = { nom: Capitain Haddock, ville: Moulinsart },

Castafiore = { nom: Castafiore, ville: Pesaro },

Tintin-[r:AMI]->Haddock,
Haddock -[r:AMI]->Castafiore;

Nous retournons maintenant dans longlet Data browser et nous activons laffichage
graphique des relations (figure 12-3).

Figure 12-3
Affichage graphique des relations

Les relations, comme les nuds, sont numrotes. Nous pouvons maintenant appliquer
toutes sortes de requtes pour traverser larbre et chercher les relations. Par exemple, la
requte suivante cherche sil y a une relation de type AMI entre Milou et la Castafiore :
START Milou=node(1), Castafiore=node(4)
MATCH Milou-[r:AMI*]->Castafiore

RETURN r;

La requte peut se lire ainsi : pour Milou et la Castafiore, sil y a une relation de type AMI
qui va de Milou la Castafiore en passant par un nombre indfini (*) de relations
intermdiaires, retourne-moi cette relation . Le rsultat est :
==> +------------------------------------+

==> | r |
==> +------------------------------------+

==> | [:AMI[2] {},:AMI[1] {},:AMI[0] {}] |


==> +------------------------------------+
==> 1 row

==> 4 ms

Conclusion
Nous vous avons brivement prsent Neo4j, et seulement du point de vue de quelques
requtes Cypher simples. Sachez que Neo4j est trs rapide, mme avec des millions de
nuds et de relations, et que son langage est trs complet. Vous disposez galement de
bibliothques clientes pour diffrents langages. Le client pour Python sappelle py2neo.
Partie III

Mettre en uvre une base NoSQL

Cette partie est consacre la mise en uvre des bases de donnes NoSQL. Dans un
premier temps, nous verrons si le passage une base NoSQL se justifie, et si cest le cas,
vers quel type de base de donnes se tourner. Nous aborderons ensuite la modlisation des
donnes et dterminerons si elle savre ncessaire en NoSQL. Linstallation et le
dploiement des moteurs NoSQL seront galement tudis, ainsi que leur supervision.
Pour finir, des exemples concrets de mise en uvre de bases NoSQL seront proposs
travers une tude de cas.
13
Quand aller vers le NoSQL et quelle base
choisir ?

Ladoption dun moteur NoSQL ne se fait pas sur un coup de tte, uniquement parce que
la technologie a lair intressante. Les donnes sont dans la majorit des cas le centre dun
systme informatique, que lon nomme justement un systme dinformation. Le choix
dun systme de gestion de donnes ne doit pas se faire selon les tendances du moment,
mais par rapport aux besoins et aux contraintes du mtier. Il est important deffectuer le
bon choix et pour les bonnes raisons.

Aller ou non vers le NoSQL

Comment les donnes vont-elles tre utilises ?


Les moteurs NoSQL prsentent certains avantages : souplesse du schma, typage
dynamique, proximit avec les langages clients, monte en charge facilite par une
approche horizontale avec sharding automatique, etc., ce qui permet une gestion plus aise
du systme dinformation. Mais cela impose aussi des contraintes. En effet, la relative
souplesse du schma et la proximit avec le langage client orientent les moteurs NoSQL
vers une organisation des donnes plutt par application que vers une centralisation et une
utilisation partage.
Le modle des bases de donnes relationnelles spare la conception logique et les
structures physiques. Les donnes atomiques et fortement types sont trs structures. Des
contraintes et des rgles mtier au niveau du serveur (par les vues, les dclencheurs et les
procdures stockes) sont mises en place. Ceci permet de grer les donnes en amont,
presque indpendamment des applications clientes, et donc de partager et rutiliser ces
donnes pour toute lentreprise. Cest une force incontestable. Mais qui va de pair avec
quelques contraintes : un peu moins de souplesse au niveau de lvolution du schma et
lobligation dune phase danalyse plus pousse au cours de laquelle les donnes sont
prdfinies avec soin.
Cela dit, un moteur orient documents comme MongoDB, ou CouchDB, regroupe ses
donnes dans une unit (le document JSON) qui correspond aux besoins dune application
(toutes les donnes ncessaires une page web, un formulaire, une commande, une
action). Lunit de travail nest plus une entit dcoupe selon la logique de la donne,
comme cest le cas pour les relations dans le modle relationnel, mais selon la logique de
lapplication, du besoin du client. Cest donc une approche plus oriente vers le
dveloppeur, et moins vers une donne considre comme centrale, qui fait la loi.
Lapproche tranche avec les habitudes des DBA, mais pourquoi pas. Toutefois, cela
implique davoir bien saisi cette nuance et den tirer toutes les conclusions, notamment en
ce qui concerne la rutilisation des donnes dans les diffrentes tapes du traitement. Par
exemple, une application de gestion qui manipule des produits, des commandes, puis un
suivi de commandes, et rutilise des donnes analytiques pour des besoins dcisionnels et
des tableaux de bord, se doit davoir des donnes accessibles selon plusieurs points
dentre, notamment pour des calculs statistiques aprs coup.
Comme nous lavons vu, les moteurs NoSQL organisent leurs donnes selon un identifiant
de ligne, une cl, appele primaire dans le modle relationnel. Afin de pouvoir faciliter
le partitionnement des donnes, il vaut mieux que ces dernires soient accdes
exclusivement par la cl, au moins dans la plupart des cas. Le besoin de recherche
lintrieur de la valeur qui est stocke avec cette cl dpend du type de moteur NoSQL.
Les moteurs orients colonnes et orients documents vous permettent de crer des index
secondaires, mais cette approche ne prsente pas la souplesse et la solidit des moteurs
relationnels. On reste dans une vision organise principalement selon la cl. En ce qui
concerne les moteurs de paires cl-valeur, comme Redis ou Riak, la partie valeur est
thoriquement opaque. Le moteur na pas de vision de cette partie, qui peut tre un objet
binaire, une classe srialise, des structures diverses. Le moteur ne possde pas les outils
permettant dinterprter et de donner sens cette donne. En thorie, il est donc
impossible dindexer ou deffectuer une recherche dans la partie valeur. Cest bien
entendu moiti vrai. En effet, Redis permet diffrents types de donnes pour la partie
valeur et optimise laccs, par exemple, un ensemble ou un ensemble ordonn. Riak,
quant lui, implmente depuis peu des index secondaires.
Il existe deux approches traditionnelles pour effectuer des recherches dans ces moteurs :
dupliquer la donne rechercher dans une autre structure o elle devient la cl, et la
valeur est la rfrence de la cl de la collection dorigine ;
lorsquon manipule du texte, indexer la partie valeur avec un moteur de recherche en
texte intgral, comme Lucene ou Solr, (voir chapitre 12, section ElasticSearch ).
Intrt dElasticSearch
Pour les schmas simples et des besoins de grande rapidit, il est intressant dopter pour une solution Redis ou
Riak + ElasticSearch.

Les avantages des moteurs relationnels


Ds que les donnes sont fortement structures et que les besoins de recherche sont divers
sur plusieurs attributs, avec la ncessit de sadapter tous types de requtes provenant
des utilisateurs, les capacits dclaratives et ensemblistes du langage SQL allies aux
techniques dindexation des moteurs SQL offrent dexcellentes performances, surtout par
leur capacit utiliser un moteur doptimisation pour tablir une stratgie procdurale au
niveau du serveur. Mme si on les considre du point de vue du dveloppement rapide, les
moteurs relationnels sont trs intressants, car loptimisation peut tre effectue en crant
des index ou des vues matrialises sans avoir changer le code client.
On pourrait rsumer les choses ainsi : si vous avez besoin dune souplesse au niveau du
schma, +1 pour le NoSQL ; si vous avez besoin dune souplesse au niveau de la richesse
des requtes, +1 pour les moteurs SQL.
Une autre consquence de la diminution de la modularit des donnes imposes par
lorganisation cl-valeur est la rutilisation des structures, comme les documents,
organises par dautres cls. Par exemple, si vous stockez des commandes de produits
dans des documents MongoDB dont la cl est un numro de commande, vos choix seront
ensuite limits si vous souhaitez organiser vos donnes selon le client (pour suivre de son
compte) ou selon le produit (pour grer les stocks). Vous serez sans doute oblig de
dupliquer la donne dans dautres structures. Pour cette raison, les bases NoSQL ne sont
pas des moteurs intressants pour des applications de gestion classiques, pour lesquelles le
modle relationnel est plus intressant.
En rsum, si vous avez besoin dun systme dinformation dans lequel les donnes
doivent tre organises dune faon centrale, partages entre diffrentes applications,
recherches selon de multiples critres, il vaut mieux vous orienter vers un moteur
relationnel. En revanche, si vos cas dutilisation sont ddis peu dapplications bien
cibles, et que vous avez un modle o la plupart des accs seront faits selon une cl bien
dfinie, le paradigme NoSQL est intressant.

Que doit-on stocker ?


On peut se poser la question autrement : de quelle nature sont mes donnes ? Sagit-il de
donnes fortement structures et types avec une certaine stabilit ou plutt des donnes
dstructures ou semi-structures, dont les attributs varient fortement selon les cas ? Un
produit de mme type ou une facture prsente des attributs assez stables. En revanche, un
article de blog na pas beaucoup dattributs, ceux-ci pouvant tre assez variables : un texte
plus ou moins long, des images, de la vido, du son, lments difficiles grer dans un
moteur relationnel. Cette structure est-elle stable ou est-il prvu quelle soit fortement
modifie ? Un moteur orient documents peut tre une bonne solution : en versionnant ds
le dpart le document stock, le modle peut voluer sans changement de structure dans le
moteur, et avec une gestion conditionnelle dans le programme client.
On peut aussi rflchir selon le type des donnes. Des cas dutilisation comme les blogs
ou les rseaux sociaux reprsentent des structures de donnes plutt orientes texte. Les
applications de gestion, qui sont des cas dutilisation typiques des moteurs relationnels,
sont plus orientes autour des donnes chiffres, les parties texte tant limites aux
libells, rfrences, parfois aux descriptions. Dans une application de gestion, les donnes
chiffres doivent tre retrouves selon plusieurs critres et des calculs doivent tre
effectus selon diffrents niveaux de regroupement. Une base de donnes relationnelle est
vraiment plus adapte dans ce cas. Ce sont finalement des choses que lon reprsente dj
naturellement de manire tabulaire dans un tableur, en crant des rfrences entre cellules.
La base de donnes relationnelle en est lextension beaucoup plus puissante, mais qui reste
un peu dans le mme concept. Une base de paires cl-valeur est lextension des listes de
donnes, et un moteur orient documents est lextension dune structure hirarchique de
donnes orientes texte, quon peut aussi reprsenter plus facilement dans du XML que
dans une structure tabulaire.
La diffrence dapproche avec le relationnel
Le NoSQL implique galement une diffrence au niveau de la phase de conception. Un
projet informatique traditionnel incluant la gestion de donnes relationnelles comporte une
phase darchitecture et danalyse fonctionnelle spcifique. La phase de modlisation est
trs importante dans un tel projet, mme sil est dfini comme agile. Il est vital de
comprendre le modle de donnes lavance, et il sagit souvent dun travail effectu par
un spcialiste. Lapproche dun moteur NoSQL est plus informelle, elle se plie beaucoup
plus aux besoins de lapplication cliente elle-mme. Le choix dun moteur NoSQL est
souvent motiv par des raisons non fonctionnelles, mais sur des bases techniques :
volumtrie, performances, distribution. Mais comme nous lavons vu, cela dpend du type
de moteur NoSQL. Une simple base cl-valeur, voire une base oriente documents, entre
dans cette catgorie informelle . Un moteur orient colonnes comme Cassandra, en
raison de la centralit plus forte de ses donnes et dune plus grande formalisation des
structures, se rapproche plus dun moteur relationnel du point de vue de la phase de
conception.
Une autre question est celle du niveau de comptence des quipes. Une base NoSQL est
plus accessible aux quipes de dveloppeurs habitus des langages objet ou impratifs. Il
vaut mieux finalement faire du NoSQL que du SGBDR mal conu en utilisant un ORM
(Object-Relational Mapping) comme Hibernate ou Entity Framework.

Le problme des comptences


Les comptences sont un lment important de la prvision de monte en charge. Monter
en charge avec un SGBDR ncessite des comptences dans ce domaine : tuning,
optimisation de la structure, des index et du code SQL, mise en uvre de mcanismes
comme le partitionnement de table ou les vues matrialises. Obtenir de bonnes
performances demande une attention constante la base de donnes, depuis les premiers
moments de la phase de conception et tout le long de la vie de lapplication. Chaque tape
de la mise en uvre dune base de donnes relationnelle est importante pour les
performances (le modle de donnes, le code SQL, lindexation et limplmentation
physique). Les erreurs sont difficiles corriger aprs coup.
De plus, un des principaux critres de qualit dun moteur relationnel est son moteur
doptimisation, cest--dire le sous-systme du moteur relationnel charg de transformer la
requte dclarative en un plan dexcution procdural. Beaucoup de personnes qui sont
passes du relationnel au NoSQL, dues par les performances du premier, citent une
utilisation de MySQL. Or, MySQL est sans doute un excellent moteur, mais il natteint pas
la qualit et les performances des SGBDR commerciaux, ou mme de PostgreSQL si on
reste dans le monde du libre. Le problme peut alors devenir un problme de licence : on
se retrouve devoir payer trs cher un moteur qui peut offrir dexcellentes performances
la condition que les quipes qui le mettent en uvre en comprennent les subtilits, ce qui a
galement un certain cot en termes de temps et de formation. Dans ce cas, mme si dans
labsolu lutilisation du NoSQL ne se justifie par rellement, il peut constituer un choix
plus simple et moins coteux.
Finalement, monter en charge avec un moteur NoSQL ncessite peu de comptences
logicielles. Comme il sagit principalement dune distribution de traitement, il suffit
dajouter de nouvelles machines et de les configurer lidentique des machines dj
installes pour quelles soient prises en compte par des mcanismes comme le sharding ou
lalgorithme MapReduce.
Intgr dans la plupart des moteurs NoSQL, MapReduce reprsente lalgorithme de choix
pour effectuer aprs coup des traitements sur les donnes avec des performances
raisonnables, lquivalent des calculs quon peut raliser avec le langage SQL, comme les
agrgats. Mais, sur des tailles de donnes raisonnables, disons par exemple jusqu
quelques traoctets, MapReduce ne peut rivaliser en performance pour les calculs avec un
moteur relationnel ou un systme dcisionnel. MapReduce offre, nous lavons dit, des
temps de rponse raisonnables, mais il nest pas conu pour retourner des rponses dans
des conditions de temps rel.

Quels sont les besoins transactionnels ?


Sauf rares exceptions, les moteurs NoSQL nont pas de notion de transaction qui
permettrait de rendre atomique des modifications opres sur plusieurs lignes ou plusieurs
documents. Des moteurs comme MongoDB permettent de simuler des relations entre
documents en stockant la cl dune autre collection (un type DBRef dans MongoDB), sinon
le traitement est opaque pour le moteur et gr uniquement par la logique du code client,
sans aucun moyen de rendre ces oprations sur plusieurs donnes atomiques. Les besoins
transactionnels complexes sont finalement rares dans beaucoup dapplications, et dans les
cas o ce besoin se fait sentir (application financire, dernier stade du panier dachat, etc.),
des moteurs relationnels ou qui supportent pleinement lacidit de la transaction (tels que
Neo4j dans le monde NoSQL) devront tre choisis. Les moteurs orients colonnes
permettent la lecture et lcriture de dterminer un niveau de cohrence, ils constituent
donc un choix souple. Cependant, ils sont privilgier pour des besoins de volumes
importants, car ils sont conus pour tre distribus. Installer HBase ou Cassandra sur une
seule machine, par exemple, na pas vraiment de sens.

Rsum des cas dutilisation


En rsum, quand est-il une bonne ide dutiliser une base NoSQL ? Prenons dabord la
question du point de vue des atouts du non relationnel :
les donnes que vous devez grer sont peu structures, et les structures sont plutt
changeantes. Il sagit par exemple de texte plus ou moins long, de donnes saisies par
les utilisateurs sans canevas trop contraignant. Vous allez naturellement vous tourner
vers une base oriente documents ;
vous devez privilgier les performances dcriture et de restitution, et vous assurer que
laccs aux donnes se fasse toujours en dessous de quelques millisecondes. Une base en
mmoire comme Redis sera alors un bon choix ;
vous devez stocker et manipuler de grandes quantits de donnes, par exemple plusieurs
traoctets. Un moteur distribu sera alors un choix naturel ;
vous accderez vos donnes principalement par un seul point de recherche, qui
constituera la cl de vos documents ou de vos paires cl-valeur. Par exemple, vous
voulez afficher sur une page toutes les donnes dun utilisateur. Un document JSON qui
stocke ces informations et que vous requterez par lidentifiant de lutilisateur (la cl)
sera idal.
En revanche, le NoSQL prsente quelques dsavantages qui feront que vous privilgierez
un moteur relationnel dans certains cas :
vous stockez et manipulez des donnes trs structures, sur lesquelles vous voulez
appliquer diffrents calculs, du reporting selon plusieurs axes, et que vous voulez
pouvoir chercher selon diffrents critres ;
vos donnes sont manipules depuis plusieurs applications clientes, et vous voulez
pouvoir assurer la qualit de ces donnes en appliquant des contraintes au niveau du
serveur ;
vous effectuez des recherches ou des traitements complexes, en masse, sur des
ensembles de donnes. Dans ce cas, les moteurs relationnels vous permettent de
manipuler aisment, de faon ensembliste, vos donnes avec du code qui sexcute sur
le serveur.
Une des grandes forces des moteurs relationnels reste la possibilit de traitement du ct
du serveur amene par le langage SQL.

Choix par rapport au type dapplication


On peut aussi considrer le choix dun moteur relationnel ou NoSQL globablement par le
type dapplication de donnes dveloppe. Voici quelques exemples dapplications et du
raisonnement concernant le choix dun moteur.
Blog un blog est principalement constitu de texte (articles, commentaires) et de listes
(mots-cls, catgories). Les articles de blog sont principalement appels par un critre,
la date de larticle, auquel sajoute ventuellement lidentifiant de lauteur et la
catgorie. Un moteur NoSQL orient documents, comme MongoDB ou CouchDB, est
particulirement indiqu pour ce genre dapplication, auquel on peut ajouter les
applications de messagerie, les bases de connaissance, les magazines. Il ny a aucun
avantage utiliser un moteur relationnel dans ce type dapplication. Pour les
fonctionnalits de recherche, les index des moteurs relationnels ne seraient daucune
utilit sur du texte long. Lindexation en plein texte des documents JSON avec un outil
comme ElasticSearch est donc la meilleure solution.
Donnes de gestion, ERP les donnes de gestion sont souvent trs structures, avec
des donnes atomiques bien dfinies, des besoins de manipulation partir de plusieurs
briques logicielles clientes et des besoins de recherches multicritres et de manipulations
complexes. De plus, les volumes de donnes restent raisonnables et ncessitent rarement
de distribuer le traitement. Toutes ces raisons font quun SGBDR reste le meilleur choix
dans ce genre de cas.
Reporting et analyse OLAP les besoins de reporting impliquent de faire des
recherches travers de grandes quantits de donnes bien structures, afin deffectuer
des calculs dagrgation sur plusieurs axes danalyse. Un moteur relationnel, ou mieux,
un moteur OLAP ou une solution de reporting qui manipule directement des structures
multidimensionnelles est privilgier au NoSQL dans ce cas, sauf si le volume des
donnes devient trs important, auquel cas vous aurez besoin de distribuer le traitement.
Un moteur orient colonnes, comme HBase ou Cassandra est alors une bonne solution,
quitte stocker des donnes prcalcules et dupliques selon plusieurs cls
correspondant aux axes danalyse, et profiter de traitements en MapReduce.
GED, Gestion lectronique de documents la gestion lectronique de documents
consiste dmatrialiser les documents et les classer dans le systme informatique. Il
ny a pas forcment de gain apport par les SGBDR dans ce modle, vous pouvez
utiliser un moteur NoSQL. Les bases de donnes en paires cl-valeur peuvent contenir
des documents binaires dans la partie valeur, et un moteur comme MongoDB comporte
une fonctionnalit de stockage de fichiers nomme GridFS. Ceci dit, comme en ce qui
concerne les SGBDR, il est souvent plus efficace dorganiser les fichiers sur un systme
de fichiers partag et de rfrencer seulement les liens dans la base de donnes. Les
moteurs relationnels comportent souvent un type de donnes nomm DATALINK ou
FILESTREAM qui permet de stocker les binaires sur un emplacement disque tout en
conservant une cohrence transactionnelle. Cest une fonctionnalit utile si vous optez
pour un moteur relationnel.
E-commerce le-commerce est typiquement un domaine o les moteurs NoSQL
peuvent tre utiliss en parallle avec les SGBDR. La partie catalogue, qui comporte des
donnes semi-structures en lecture seule, peut bnficier du stockage en documents
JSON ou des performances apportes par des moteurs en mmoire comme Redis. Une
indexation avec ElasticSearch ajoute les fonctionnalits de recherche dans le catalogue.
Le panier dachat, sil doit tre distribu pour pouvoir monter en charge facilement, peut
tre conserv dans un moteur distribu comme Riak, Cassandra ou MongoDB. Quant
la partie validation des achats, la ncessit de la gnrer transactionnellement vous
poussera privilgier un moteur relationnel, quitte partitionner les donnes sur
plusieurs machines manuellement en faisant un choix partir du client, par exemple
avec un modulo du hashcode de votre identifiant client calcul dans votre application
cliente.
Logistique les applications logistiques peuvent bnficier du NoSQL : suivi dun colis
ou dun container via un document JSON dans lequel sont listes toutes les tapes du
transport, recherche dun chemin optimal en utilisant une base de donnes oriente
graphes comme Neo4J, stockage des manifestes et listes de colisage dans des documents
JSON La logistique est un domaine dapplication o il est intressant de mettre en
place plusieurs solutions de gestion de donnes selon les besoins. Une base de donnes
relationnelle peut rester la colonne vertbrale des donnes par sa gestion centralise de
ces dernires bien structures, et des moteurs NoSQL peuvent tre utiliss pour offrir
des fonctionnalits spcifiques.
Donnes spatiales plusieurs moteurs NoSQL commencent implmenter des
fonctionnalits de calcul spatial, comme les calculs de distance entre les points de
MongoDB, ou le support naissant de la spcification GeoJSON
(http://www.geojson.org/, une dfinition de document JSON comportant des objets
spatiaux comme des points ou des polygones) dans CouchBase Server.
Il ny a rien toutefois qui soit suffisamment avanc dans le monde NoSQL lheure
actuelle pour dvelopper de relles applications spatiales. Il faut donc rester pour
linstant avec des outils qui sappuient sur les SGBDR, comme lextension PostGIS de
PostgreSQL, qui supporte GeoJSON.

Quelle base choisir ?

Comparaison des principales bases NoSQL


Le monde NoSQL est une nbuleuse de moteurs relativement diffrents, quil nest pas
toujours ais de rassembler sous la mme bannire. Si vous dcidez dopter pour un
moteur NoSQL, il convient de choisir celui qui sera le plus adapt vos besoins, chacun
des moteurs rpondant des cas dutilisation trs diffrents.
Il nous a paru utile de rcapituler sous une forme synoptique les principales
caractristiques des moteurs NoSQL dont nous avons parl jusqu prsent. Nous avons
essay de rsumer les critres de choix de chaque moteur, la structuration des donnes
quil permet, sa faon de grer la problmatique de la cohrence, sil permet ou non la
distribution des donnes sur plusieurs nuds, en quel langage il est crit, son mode de
licence, le protocole de communication utilis et les points forts du moteur. Cela vous
permettra de disposer dun tableau de rfrence pour une premire analyse selon vos
besoins. Voici donc la liste rsume des moteurs.

HBase
choisir pour : HBase est un choix intressant uniquement si vous prvoyez de grer un
volume de donnes trs important. Bas sur Hadoop, il permet de distribuer les donnes en
utilisant le systme de fichiers distribu HDFS (Hadoop Distributed File System)
dHadoop. Cela na donc pas de sens de vouloir utiliser HBase sur un systme non
distribu. De plus, sa mise en uvre est relativement complexe.
Types de donnes manipules : base de donnes oriente colonnes. Les donnes sont
organises selon des cls de ligne (row key), puis en familles de colonnes, puis en
colonnes. La cellule est compose dun nom de colonne, de la valeur et dun timestamp.
La valeur est simplement stocke sous forme doctets, il est inutile de dfinir des types de
donnes ou de prdfinir les colonnes, seules les familles de colonnes doivent tre
prdfinies.
Maintien de la cohrence : garantie ACID sur une ligne (cest--dire plusieurs familles
de colonnes) depuis HBase 0.92. Cela veut dire que des commandes qui appliquent des
modifications sur plusieurs lignes ne constituent pas une opration atomique, mais une
suite de modifications de lignes individuellement atomiques, qui vont retourner un tat de
succs ou derreur pour chaque ligne.
Mode de distribution : bas sur Hadoop et HDFS, avec matre centralis. Un cluster
HBase est constitu dun matre (HMaster) qui maintient les mtadonnes du cluster et gre
des serveurs de rgion (RegionServer). Chaque rgion contient une partie des donnes.
Dvelopp en : Java. Toute la pile Hadoop, HDFS et HBase est en Java.
Licence et support : Apache 2.0. HBase est un projet de la fondation Apache
(http://hbase.apache.org/license.html). La socit amricaine Cloudera
(http://www.cloudera.com/) distribue une dition de Hadoop et HBase avec support
nomme Cloudera Enterprise.
Protocole : REST et Thrift. Il existe galement une API Java native et une interface Avro.
Points forts : utiliser pour le Big Data, trs bonne monte en charge horizontale, solidit
de la conception et excellente tolrance au partitionnement. HBase est utilis par des
acteurs comme Facebook pour stocker tous les messages de ce rseau social, ce qui
reprsentait en 2009 plus de 150 traoctets de nouvelles donnes par mois
(https://www.facebook.com/UsingHbase). Sa popularit fait quil est en constante
amlioration de par le dveloppement de Cloudera et les contributions de la communaut.
Par exemple, Facebook a apport de nombreuses amliorations au moteur.

Cassandra
choisir pour : choix intressant pour de grands volumes de donnes et les besoins de
bases distribues, hautement disponibles et dcentralises, sur de multiples data centers.
Comme pour HBase, Cassandra nest pas un choix intressant pour des volumes de
donnes moyens ou des systmes non distribus.
Types de donnes manipules : base de donnes oriente colonnes. Donnes organises
dans un keystore (lquivalent dune base de donnes) par famille de colonnes
(lquivalent dune table) selon une cl et des colonnes. La cellule est compose dun nom
de colonne, de la valeur et dun timestamp. Les familles de colonnes doivent tre
prdfinies, mais les colonnes dans une famille ne font pas lobjet dun schma dfini.
Contrairement HBase, Cassandra a une cl par famille de colonnes, ce qui le rapproche
plus dun modle de base de donnes relationnelle. Mme si Cassandra stocke ses donnes
sous forme de tableaux doctets, labstraction amene par CQL 3 le rend trs proche au
ressenti dun moteur relationnel.
Maintien de la cohrence : la cohrence en criture et en lecture sont paramtrables. Par
exemple, on peut forcer une criture, ou une lecture, tre valide sur plusieurs rplicas
avant dtre considre comme effectue. partir de Cassandra 1.1, lACIDit est
garantie par ligne.
Mode de distribution : dcentralis. Chaque nud est indpendant et il ny a pas besoin
de serveur matre. Les connexions utilisateurs peuvent se faire sur nimporte quel nud,
qui se chargera de rediriger le client vers le nud qui contient les donnes souhaites. La
rpartition est ralise par vnodes ou, historiquement, par hachage consistant.
Dvelopp en : Java.
Licence et support : Apache 2.0. Cassandra est un projet de la fondation Apache. La
socit amricaine DataStax (http://www.datastax.com/) maintient une dition de
Cassandra, nomme DataStax Enterprise, gratuite au tlchargement avec une option
dabonnement avec support.
Protocole : lAPI Cassandra est de type natif pour CQL. Une interface Thrift existe mais
elle est dprcie.
Points forts : implmentation solide, systme dcentralis, souplesse de configuration,
cohrence paramtrable. Ne ncessite pas un systme de fichiers distribu comme HBase.
Cassandra est un produit mature, largement utilis et trs populaire, cest une excellente
solution pour btir un systme de gestion de donnes volumineux et dcentralis.

CouchDB
choisir pour : CouchDB est la base de donnes du Web. Son orientation documents et
son interface REST excellent pour construire des projets web ou destination des
terminaux mobiles. CouchDB est prfrer pour les besoins o la richesse fonctionnelle
lemporte sur les grands volumes et la disponibilit. Pour les besoins de grandes
performances, voir du ct de Couchbase Server, le successeur de CouchDB.
Types de donnes manipules : document JSON.
Maintien de la cohrence : cohrence finale (eventual consistency). la base, CouchDB
ntant pas distribu, la cohrence locale est gre par un verrouillage optimiste :
CouchDB maintient automatiquement un numro de version sur chaque document. Pour
modifier un document existant, il faut indiquer son dernier numro de rvision, sinon la
mise jour est refuse.
Mode de distribution : pas de distribution native. Un systme de rplication des donnes
permet dchanger les modifications dune base avec un autre serveur, mais cela doit tre
gr manuellement. Pour une version nativement distribue, voir Couchbase Server.
Dvelopp en : Erlang, un langage dvelopp lorigine par la socit Ericksson et qui
est conu spcialement pour le traitement parallle et linformatique distribue.
Licence et support : Apache 2.0. CouchDB est un projet de la fondation Apache.
Protocole : REST exclusivement. Il ny a pas dinterface rapide et plus bas niveau.
Points forts : grande richesse fonctionnelle au niveau du serveur, vues, filtres dans des
documents de design et incorporation possible de traitements complexes sur le serveur, ce
qui peut lamener devenir galement un vrai serveur applicatif. La simplicit de mise en
uvre est aussi un des points forts de CouchDB, quon a tiquet de base de donnes du
Web . Fonctionnalits de rplication et de surveillance des changements simples mais
solides et bien faites.

Couchbase Server
choisir pour : Couchbase est un moteur dcentralis paires cl-valeur et document
JSON. Cest un excellent moteur pour des besoins de stockage simple ou de type
document avec un besoin dlasticit dans la monte en charge.
Types de donnes manipules : paire cl-valeur et document JSON.
Maintien de la cohrence : cohrence forte, simplement parce que lcriture et la lecture
sont ralises sur le mme nud, qui est matre des donnes. Les rplicas existent pour la
redondance uniquement.
Mode de distribution : dcentralis. Chaque nud est indpendant et il ny a pas besoin
de serveur matre. Les bibliothques clientes qui utilisent le concept de smart client
rcuprent en cache local la topologie du rseau et adressent directement le bon nud
lorsque ces clients font un get dune cl. La rpartition est faite par vbucket, un type de
vnode.
Dvelopp en : C++ et Erlang.
Licence et support : Apache pour ldition communautaire, et commerciale.
Protocole : memcached pour laccs aux cls, REST pour laccs aux vues.
Points forts : excellentes performances dans laccs aux cls, richesse fonctionnelle au
niveau du serveur travers les vues, lasticit de la monte en charge.

MongoDB
choisir pour : tout type de besoin de stockage de documents, cest--dire de donnes
structures : srialisation dobjets, pages web, formulaires de saisie, informations
dapplications. La reprsentation en documents permet dutiliser MongoDB pour des
structures proches de ce qui est stock dans une base relationnelle, ou des structures
hirarchiques, avec une plus grande souplesse dans le schma de donnes. Un systme
dindexation secondaire permet deffectuer des recherches dans les donnes et de
rcuprer des documents par dautres points dentre que la cl.
Types de donnes manipules : BSON, un format JSON binaris pour tre plus
compact.
Maintien de la cohrence : cohrence finale travers les rplicas. Les critures ont une
option (write concern) pour indiquer quelles sont valides si elles ont crit sur un certain
nombre de rplicas ou sur une majorit (N/2+1). La durabilit est optionnelle travers
lactivation dun journal (Write-ahead log). Une mise jour est atomique par document, il
ny a pas de transaction multidocument possible.
Mode de distribution : centralis. Autosharding et rplication automatique. Les
mtadonnes des shards sont centralises sur un serveur de configuration, qui peut lui-
mme tre rpliqu pour fournir de la redondance. La connexion client se fait aussi sur un
serveur matre, qui redirige la requte vers le bon serveur de shard. Ce serveur matre peut
lui aussi tre redondant.
Dvelopp en : C++.
Licence et support : GNU AGPL v 3.0, licence Apache pour les pilotes. La licence
AGPL permet de sassurer que les contributions retournent la communaut. Des licences
commerciales peuvent tre acquises auprs de MongoDB Inc.
(http://www.mongodb.org/display/DOCS/Licensing).
Protocole : natif, question-rponse sur un socket.
Points forts : moteur solide, bonnes performances. Simplicit dutilisation du point de
vue du dveloppement client et bonne intgration des pilotes dans les langages. Support
commercial par la socit qui dveloppe le produit, MongoDB Inc. Ses capacits de
sharding et de rplication automatiques permettent de monter en charge horizontalement
au fur et mesure de laugmentation des besoins.
Riak
choisir pour : Riak est un entrept de paires cl-valeur bien conu, solide, performant
et qui monte trs bien en charge. Cest un excellent choix pour un moteur qui doit la fois
tre distribu et offrir une latence faible, sur des systmes qui doivent tre prts monter
en charge trs rapidement et de faon automatique.
Types de donnes manipules : paires cl-valeur. La valeur est normalement opaque,
mais elle peut tre indexe si cest du JSON.
Mode de distribution : dcentralis par hachage consistant, la manire de Dynamo
dAmazon. Pas de serveur matre et chaque nud est indpendant. Les connexions
utilisateurs peuvent seffectuer sur nimporte quel nud, qui se chargera de rediriger le
client vers le nud contenant les donnes souhaites.
Dvelopp en : Erlang, un langage dvelopp initialement par la socit Ericksson et qui
est spcialement adapt au traitement parallle et linformatique distribue.
Licence et support : Apache 2.0. Riak est dvelopp par la socit Basho
(http://basho.com/), qui en distribue deux versions commerciales : Riak Enterprise, qui
tend les fonctionnalits de Riak en ajoutant une rplication sans matre et la supervision
en SNMP, et Riak Cloud Storage pour lutilisation de Riak dans le cloud.
Protocole : Protobuf et REST. Protobuf est bien sr privilgier pour de meilleures
performances. Linterface REST est intressante pour les oprations dadministration ou
un accs aux donnes par des applications mobiles.
Points forts : une des implmentations qui se rapprochent le plus de Dynamo dAmazon
et qui reprend ses solutions techniques : hachage consistant, read repair, hinted handoffs,
etc. Support commercial par la socit Basho qui dveloppe le produit. Offre de bonnes
performances et de bonnes capacits de monte en charge.

Redis
choisir pour : Redis est un excellent choix pour maintenir des donnes en mmoire
pour un accs en temps rel trs rapide. Cest une forme de remplacement dun cache tel
que memcached pour offrir une plus grande richesse fonctionnelle et une manipulation de
structures de donnes plus riches.
Types de donnes manipules : la base, une chane binary-safe dans laquelle on peut
donc stocker et manipuler des valeurs numriques et binaires. partir de ce type de
donne de base, Redis offre des listes, des ensembles, des ensembles tris et des tables de
hachage. Ces structures permettent de grer beaucoup de besoins de manipulations de
donnes, et ces structures sont optimises en mmoire.
Maintien de la cohrence : pas de notion particulire de cohrence. Une seule criture est
bien sr atomique. Une pseudo transaction peut tre dfinie pour excuter plusieurs
instructions en une seule fois sur un mode de mise en attente et dempilement des
commandes, et dexcution groupe la fin.
Dvelopp en : ANSI C.
Licence et support : BSD (Berkeley Software Distribution Licence), une licence libre peu
contraignante qui permet dutiliser, de modifier ou de distribuer Redis sans restriction, que
ce soit pour des besoins libres, propritaires, gratuits ou commerciaux. Il ny a pas de
support officiel. Redis est principalement dvelopp par Salvatore Sanfilippo et Pieter
Noordhuis, engags par VMWare pour dvelopper Redis plein temps en licence libre.
Protocole : natif, mode question-rponse travers un socket.
Points forts : extrme rapidit, solidit et intelligence de la construction, richesse
fonctionnelle du langage pour la manipulation des donnes, oprations sur les ensembles.

En rsum
Terminons ce chapitre par un tableau comparatif synthtique qui, pour chaque moteur
trait dans ce livre, offre quelques pistes dutilisation.
Tableau 13-1. Comparatif des bases NoSQL

Conclusion
Le choix dun moteur de base de donnes se fait partir des besoins, et certainement pas
partir dun a priori technologique. Autant que possible, ce choix doit aussi se baser sur des
tests raliss en interne et prenant en compte les contraintes du business. Cest la fois un
choix dcisif, car il est difficile de revenir en arrire lorsque toutes vos donnes sont
gres dans un systme, mais cest aussi un choix qui nest pas forcment fatal, car il est
possible dadapter son traitement, jusqu un certain point, au moteur choisi. Les axes de
choix comportent les fonctionnalits, les performances et la solidit du produit. Il est par
exemple possible de faire le choix, pour un systme de production, dun moteur NoSQL
encore jeune, mais il faut alors pouvoir contourner les problmes rencontrs lors de
lutilisation. Nous pensons notamment des outils, comme Couchbase Server, dont nous
navons pas parl dans ce livre, parce quils sont trop jeunes, mais qui sont parfois mis en
production dans des entreprises qui essuient les pltres. Donc, votre choix devra se faire
selon les axes que nous avons indiqus dans ce chapitre, mais aussi aprs des tests aussi
srieux que possible pour vous assurer que le moteur rponde vos besoins, et quil est
capable de tenir la charge solidement, comme vous le souhaitez. Souvenez-vous en plus
dune chose : dans le monde NoSQL, un moteur correspond souvent une application
cliente, vous pouvez donc tout fait mettre en place plusieurs solutions de gestion de
donnes selon vos besoins, et tablir des fertilisations croises entre les SGBDR, les
moteurs NoSQL et des outils comme ElasticSearch pour ajouter les fonctionnalits
voulues.
14
Mettre en place une solution NoSQL

Mme si les moteurs NoSQL sont plutt organiss selon une optique de dveloppement
rapide, et que ltablissement dun schma prliminaire nest pas ncessaire, cela ne veut
pas dire que leur mise en place doit tre prise la lgre.
Dans ce chapitre, nous allons aborder quelques considrations darchitecture et de
modlisation des donnes.

Architecture et modlisation
Comme voqu dans le chapitre prcdent, on peut se demander si la modlisation des
donnes et larchitecture ont encore un sens dans le monde NoSQL. Certainement, et pour
plusieurs raisons.
Tout dabord, un moteur NoSQL est souvent utilis en complment de donnes structures
dans un moteur relationnel. Pour Google, par exemple, MySQL est toujours un moyen
important de stocker des donnes structures, paralllement BigTable. Les questions
darchitecture qui se posent ne concernent donc plus seulement la manire de modliser
les donnes, mais galement lendroit o les stocker. Traditionnellement, les bases
relationnelles sont conues en se posant des questions telles que :
Doit-on sparer telles tables dans des schmas ou des bases de donnes diffrents ?
Faut-il sparer des domaines (des colonnes) en colonnes plus atomiques ? Par exemple,
faut-il dissocier le numro, le type de voie et le nom de la voie dans une ligne
dadresse ?
La structure des donnes est-elle susceptible dvoluer, par exemple en ajoutant de
nouveaux attributs ou en changeant des informations de rfrence ?
Ces questions traitent donc de la structure des donnes et de leur utilisation dans le cadre
du projet ou de lentreprise. Dans une conception incluant du NoSQL, les questions
souleves seront, par exemple, les suivantes :
Devons-nous chercher les donnes et sur quels critres ?
Quel est le rapport entre les lectures et les critures ?
Les donnes doivent-elles tre opaques pour le moteur, ou faut-il quil puisse les traiter,
par exemple en appliquant des oprations de MapReduce du ct du serveur ou des
oprations de validation ?
Faut-il effectuer des recherches sur les donnes, en dautres termes, permettre des
recherches sur des critres autres que la cl ?
Les donnes doivent-elles tre souvent rutilises par dautres applications ou dautres
services de lentreprise ?
Faut-il effectuer des calculs complexes ou lourds sur les donnes, tels que des agrgats
ou des analyses temporelles ?
Quelle est la latence acceptable daccs aux donnes ? Faut-il privilgier les
performances ou la capacit supporter un fort volume ?
Ces questions tournent principalement autour de lutilisation des donnes. La premire
question fondamentale pour dcider si le choix doit se porter sur un moteur relationnel ou
un moteur NoSQL est sans doute la question de la cl : se trouve-t-on devant un modle
o un accs via une cl, et seulement via cette cl, est possible, ou faut-il pouvoir
interroger les donnes de faon complexe ? Plusieurs types de besoins se contentent
parfaitement dun accs par la cl : gestion de profils et de comptes utilisateurs, stockage
de logs, informations de consommation ou dutilisation de services, pour nen citer que
quelques-uns.
Les questions qui viennent aprs la dtermination de la cl permettent de faire le choix
dun modle de stockage, parmi les diffrentes formes proposes par les moteurs NoSQL.
La structure relationnelle est une structure simple, en deux dimensions : lignes et
colonnes, qui reprsentent bien des donnes fortement structures. Le stockage dans un
moteur NoSQL, tout en tant aussi trs simple en apparence, permet de stocker des valeurs
autrement plus complexes, ce qui procure une grande souplesse. Le modle cl-valeur,
notamment, allie simplicit et grande puissance car il rpond un grand nombre de cas
dutilisation, offre dexcellentes performances et lavantage de la facilit de distribution.
De plus, la valeur pouvant tre nimporte quoi, il est facile dy stocker tous types de
donnes. Ds que la donne doit cesser dtre opaque au moteur, il faut penser la
structurer en document, entendez du JSON.

Stocker du XML
Il est ventuellement possible de manipuler du XML, si cest le format avec lequel vous
travaillez nativement dans vos applications clientes, pour changer des donnes par
exemple. Le stockage se fera toujours en JSON, mais la conversion sera assure par le
code client, ou du code sur le serveur, en utilisant la fonction eval() de MongoDB ou les
vues dans CouchDB. Ainsi, dans les vues en CouchDB, vous pouvez manipuler du XML
en utilisant linterprteur choisi, comme Python ou JavaScript.
Utiliser E4X pour gnrer du XML
En utilisant linterprteur JavaScript par dfaut, vous pouvez aussi gnrer une sortie XML de vos documents JSON
de faon trs simple en utilisant E4X (ECMAScript for XML, la norme ECMA-357 : http://www.ecma-
international.org/publications/standards/Ecma-357.htm). Linterprteur JavaScript de MongoDB est le mme que
celui de CouchDB (SpiderMonkey), E4X est donc galement support en MongoDB.

Vous pouvez trouver un exemple dutilisation de vue gnrant du XML dans lapplication
Sofa dveloppe pour les besoins du livre CouchDB: The Definitive Guide, disponible en
ligne cette adresse : http://guide.couchdb.org/. Il sagit dune application de blog
totalement dveloppe en CouchDB, dont le code source est maintenu sur GitHub
ladresse suivante : https://github.com/jchris/sofa.
CouchApp
Sofa utilise CouchApp (http://github.com/couchapp/couchapp/), une suite doutils destins faciliter lintgration
de documents de design et de pages de template, pour crer des applications web bases uniquement sur CouchDB.
Un jeu doutils plus moderne, nomm Erica, est maintenant disponible : https://github.com/benoitc/erica.

Sofa retourne des pages de blog formates en HTML mais permet galement de rcuprer
un flux XML en format de syndication Atom. Le code source de gnration du flux est
visible ladresse suivante : https://github.com/jchris/sofa/blob/master/lists/index.js et
utilise la bibliothque CouchApp (http://couchapp.org/). Nous reproduisons ci-aprs
uniquement une fonction de ce fichier, qui suffira illustrer lutilisation trs simple de
E4X :
exports.header = function(data) {

var f = <feed xmlns="http://www.w3.org/2005/Atom"/>;

f.title = data.title;
f.id = data.feed_id;
f.link.@href = data.feed_link;

f.link.@rel = "self";
f.generator = "CouchApp on CouchDB";
f.updated = rfc3339(data.updated);

return f.toXMLString().replace(/\<\/feed\>/,);
};

Cette fonction gnre len-tte du flux Atom, en dfinissant une variable f de type XML
(dfinie pour JavaScript dans la norme ECMA-357) et en retournant sa reprsentation en
chane la fin grce lappel de sa mthode toXMLString().

Conception pilote par le domaine


La conception pilote par le domaine (Domain-Driven Design, DDD) est une approche
dfinie par Eric Evans dans son livre ponyme, Domain-Driven Design, paru chez
Addison Wesley, dont nous vous recommandons la lecture. Il sagit de principes de
gestion de projets informatiques et de dveloppement proches des mthodologies agiles
qui se marient bien avec les projets NoSQL. Le livre original est plutt pais, mais une
version rsumant la mthode est parue sous le titre Domain Driven Design Quickly,
disponible librement au format PDF et que vous trouverez facilement en effectuant une
recherche sur le Web.
Au niveau de la conception, Eric Evans insiste juste titre sur la ncessit de bien
comprendre le mtier, le domaine pour lequel le dveloppement est fait, et de modliser ce
mtier en utilisant un vocabulaire commun entre le mtier et la technique. Les phases
dtablissement de ce modle doivent impliquer galement les dveloppeurs qui vont
travailler sur le code plus tard. Cela correspond bien avec lutilisation des bases NoSQL,
qui sont trs orientes dveloppement (parce que leur mise en uvre est plus proche de la
programmation pure et simple que de la modlisation et de ladministration). Les
dveloppeurs doivent parfaitement connatre le modle et se sentir responsables de son
intgrit. La structuration des donnes sera naturellement prise en charge par ces
dveloppeurs familiariss avec le modle et les besoins du mtier.
Le modle gnr doit pouvoir tre naturellement reprsent en classes dans le langage de
programmation. Ces classes reprsentent les objets du domaine. Certaines classes sont des
entits. Elles ont une identit, cest--dire un moyen didentifier uniquement chaque
membre, laide dun identifiant aussi simple que possible et immuable dans le temps, et
non laide de lensemble de ses attributs. Cela nous renvoie notre cl dans un moteur
NoSQL, une cl unique, prfrablement technique (gnre par le systme, un UUID ou
un entier, par exemple).
Le choix dune cl technique
Que choisir comme cl dans une base NoSQL (ou dans une base relationnelle, la problmatique tant exactement la
mme) ? Une cl naturelle, cest--dire dune valeur unique existant hors du systme informatique (comme un
numro ISBN, un numro de Scurit sociale, un EAN, etc.) doit tre vite, car la cl doit rester stable, et les
risques de changement des identifiants naturels sont grands. Par exemple, LISBN (International Standard Book
Number ou numro international normalis du livre) a chang en 2007, passant de 10 13 caractres. Autre
exemple : dans le monde du mdicament vtrinaire, lancien code AMM a t remplac il y a quelques annes par
un code plus long, le GTIN. Autre raison dailleurs pour choisir une cl technique : elle sera souvent plus compacte
quun identifiant naturel.

Une des problmatiques de la vie dun dveloppement consiste grer le changement des
objets du domaine, donc des classes. Les classes sont lies entre elles par de nombreuses
relations, ce qui complexifie le modle et rend plus difficile son volution. Eric Evans
apporte une solution possible ce problme : lagrgation. Un agrgat (aggregate)
reprsente un ensemble dobjets joints et considrs comme un tout du point de vue de la
manipulation des donnes. Les objets sont regroups lintrieur dun objet racine (root)
et en sont dpendants. Si une relation doit tre effectue entre des objets spars, il faudra
passer lobjet racine, qui lui seul porte une rfrence visible de lextrieur. Cela permet
non seulement une simplification du modle, mais aussi une simplification des contraintes
transactionnelles, du maintien de la cohrence et du verrouillage. Eric Evans indique que
si ces objets sont persists en base de donnes, seul un accs par le root et son identifiant
est possible. Cest donc exactement la faon dont nous pensons le stockage dans un
moteur NoSQL orient cl-valeur ou orient documents comme MongoDB.
Les donnes dans une base NoSQL doivent donc tre penses en units, comme un fichier,
un document JSON, une valeur scalaire ou une ligne dans une famille de colonnes. Cette
unit reprsentera ce que vous souhaitez crire ou lire de faon cohrente et atomique, ce
que vous voulez sharder, ce que vous allez identifier uniquement et requter par une cl
unique.

La cohrence
La question de la cohrence des donnes est galement un point important. Dans un
SGBDR, il est inutile de sen proccuper car cest un fait acquis. Pour vous assurer de la
cohrence entre plusieurs oprations, il suffit dinitier une transaction au niveau de votre
code au moment du dveloppement. Il est inutile dvaluer cette question lors de la phase
de conception. En revanche, dans des moteurs NoSQL comme MongoDB, la cohrence
nest assure quau niveau du document. Si vous devez maintenir des niveaux de
cohrence dans vos donnes, vous devez donc vrifier que tout ce qui doit tre maintenu
cohrent est stock dans le mme document.
Une entreprise qui fera le choix du NoSQL pourra difficilement se passer de bases
relationnelles pour stocker ses donnes transactionnelles. Comment dterminer quel
endroit placer telle ou telle donne ? Et comment faire coexister les deux
environnements ? Le choix sera principalement guid par le type des donnes et les
besoins dutilisation aprs coup de ces dernires. Des donnes typiquement front-office
pourront tre stockes dans un moteur NoSQL, pour favoriser laffichage sur un site web,
le maintien de donnes peu structures ou encore pour profiter, avec des outils comme
Redis, de capacits de rendu rapide de listes, de classement, etc. En revanche, il est
conseill de conserver les donnes de back-office dans une base de donnes relationnelle,
afin de pouvoir traiter linformation avec toute la souplesse de recherche et de calcul que
permet le langage SQL, pour des besoins danalyse par exemple.
Lorsque les donnes sont structures dans une base relationnelle, il devient beaucoup plus
facile deffectuer des calculs sur ces donnes, comme des agrgats. Imaginez que vous
dveloppiez un site de ventes prives. Les informations suivantes figurent dans votre
catalogue : la description des produits, les diffrentes tailles, les images, des commentaires
ventuels dutilisateurs, etc. Tout ceci reprsente des donnes plutt orientes documents,
peu structures, de taille trs variable et qui sont toutes rfrences sur la cl du produit.
Un moteur NoSQL est donc un candidat idal pour stocker ces informations. Ainsi, vous
utiliserez, par exemple, MongoDB pour stocker le document entier, comportant la
description, les dtails techniques, les liens sur des images et une liste de commentaires
clients. Ce document sera index sur la cl, qui correspond au SKU de larticle.
SKU
SKU signifie Stock-Keeping Unit, parfois traduit en franais par Unit de gestion de stocks (UGS). Il dsigne une
rfrence lmentaire qui sert la gestion prcise des volumes en vente.

Lorsquune commande est ralise sur le site, lapplication web inscrit dans la base de
donnes relationnelle les informations relatives la vente (SKU, identification du client,
etc.) et dcrmente ventuellement le nombre dunits disponibles dans le document
MongoDB. Linscription de la vente dans la base relationnelle permet de maintenir une
cohrence transactionnelle sur ces oprations importantes, de traiter les tapes de la vente,
deffectuer des calculs statistiques pour les afficher sur des tableaux de bord, et de les
exporter par la suite dans un systme dcisionnel.

Design patterns
Les moteurs NoSQL conduisent de nouvelles pratiques et de nouvelles faons de
concevoir les donnes en gnral. Plutt que de parler de modlisation stricte, il vaut
mieux aborder le sujet sous forme de design patterns. Au lieu dtre contraignants, ces
derniers permettent de profiter de bonnes pratiques et de solutions prouves pour
rsoudre les problmes de dveloppement souvent rencontrs. En voici quelques-uns,
adapts au NoSQL.

La rduction dimensionnelle
Le principe de la rduction dimensionnelle (dimensionality reduction) est simple :
certaines donnes sont trop complexes pour tre effectivement manipules. Il est alors
souhaitable de limiter leurs attributs (leurs dimensions) et den extraire les plus
importantes, pour ne pas tenir compte des autres. Il sagit dune faon de limiter la
complexit, qui est utile dans des cas comme les besoins dapprentissage machine ou de
gestion de donnes gographiques, par exemple. MongoDB inclut un petit systme
dinformation gographique (voir ltude de cas du chapitre 16) qui rduit la complexit,
en noffrant que des points et pas de polygones, et en considrant la Terre comme une
sphre parfaite au lieu dutiliser un systme de coordonnes ou de projection. MongoDB
nest pas un systme dinformation gographique complet, mais il permet une gestion
simplifie de points gographiques pour des besoins modestes.
Dun point de vue pratique, cela signifie : identifier les besoins, liminer les donnes
inutiles (dont vous pouvez tre sr 100 % quelles ne seront jamais utiles, mfiez-vous
de ce point), ou diminuer la complexit par des modles mathmatiques, comme le calcul
dhistogrammes statistiques, les mthodes de rduction ou la transformation de valeurs
discrtes en valeurs continues.

La table dindex
Les index secondaires soulvent de vraies questions dans le monde NoSQL, alors que leur
utilisation ne fait aucun doute dans les SGBDR. Dans un moteur NoSQL, lindexation
secondaire est soit impossible, soit cantonne des recherches bien spcifiques. Une
chose est certaine, peu dindex secondaires sont crs. Les donnes dans un moteur
NoSQL ne sont pas aussi facilement manipulables que dans un moteur relationnel. Si vous
souhaitez accder vos donnes par un autre critre que la cl, vous devez donc soit crer
un index secondaire, soit gnrer vous-mme une forme dindex au moyen de la technique
de la table dindex, quon pourrait aussi appeler vue matrialise. Nous avons illustr cette
technique dans CouchDB, o elle est aise grce lutilisation de vues dans des
documents de design, qui gnrent automatiquement des index. Cette technique est aussi
couramment utilise dans les moteurs bass sur Dynamo dAmazon, comme Riak ou
Cassandra, et dans Redis. On reprend simplement les donnes et on recre une collection
dont la cl est la valeur rechercher. La valeur sera une liste de rfrences sur la cl de la
table originelle. Il faut bien entendu sassurer que cette deuxime table, ou collection, est
toujours synchronise avec la table originelle, ce qui se fait la plupart du temps dans le
code client. La figure 14-1 illustre trs simplement le concept.

Figure 14-1
Table dindex

Nous crons une nouvelle table et stockons en tant que valeur une liste de cls comportant
le nom rfrenc par la cl. Une pratique utilise dans Cassandra va dailleurs un peu plus
loin. En effet, comme le nom des colonnes nest pas fix dans une famille de colonnes, qui
est une SortedMap de colonnes, il est inutile de placer cette liste de rfrence dans la
valeur de la colonne. Il suffit de nommer cette colonne avec la liste de rfrence et de ny
placer aucune valeur. Ceci est possible parce que le nom de la colonne ne doit pas
obligatoirement tre une chane, cela peut tre nimporte quoi exprim en octets.

La cl composite
Les types de donnes qui constituent la cl des moteurs NoSQL sont, dans la grande
majorit des cas, trs souples. Vous ntes pas limit une chane de caractres
alphanumriques stricte comme dans les SGBDR. Cela vous permet dexprimer dans la
cl, comme dailleurs dans le nom des colonnes dans une base oriente colonnes, plus
dinformations quune simple valeur. Par exemple, vous pouvez ajouter lquivalent
despaces de noms en prfixe de vos cls ou de vos colonnes. Cette pratique est courante
dans Redis ou Cassandra.
En Redis, comme nous travaillons souvent dans un espace de cls unique, il est utile de
prfixer les cls pour indiquer quoi elles servent. Prenons un exemple : nous voulons
garder les informations dun utilisateur, une liste de ses photos et une liste de ses amis.
Nous pouvons structurer les cls comme suit :
User:rudi@babaluga.com
Images:rudi@babaluga.com
Friends:rudi@babaluga.com

La premire cl indique que nous allons stocker les informations relatives lutilisateur
dont lidentifiant est rudi@babaluga.com. La valeur sera probablement une table de hachage
pour conserver des paires cl-valeur de proprits. Pour conserver les images, nous crons
une liste dadresses dimages sous forme dURI, que nous stockons dans la cl
Images:rudi@babaluga.com. Pour retrouver les images de lutilisateur, notre code client naura
qu crer la cl avec une concatnation de la chane Images : et de lidentifiant
utilisateur, et appeler un LRANGE de cette cl. Le raisonnement est le mme pour la liste des
amis de lutilisateur.
Dans Cassandra, une pratique similaire permet de classer les colonnes prsentes dans la
famille de colonnes en sous-groupes, comme dans un schma de la norme SQL. Dans une
famille de colonnes User, nous pouvons crer des colonnes Adresse:CodePostal, Adresse:Ville et
Adresse:Pays, ce qui permet de qualifier les colonnes, au lieu de crer des supercolonnes et
de stocker ladresse lintrieur (la supercolonne nest pas toujours une bonne pratique en
termes de performance).
Attention au langage CQL
Cette solution fonctionne trs bien pour un accs natif travers Thrift, mais attention si vous souhaitez utiliser le
langage CQL. Celui-ci, pour conserver une forme de compatibilit avec SQL, ne reconnat pas les noms de
colonnes qui ne sont pas alphanumriques ; Cela vous obligera protger vos colonnes par des guillemets doubles
chaque utilisation, ce qui peut se rvler pnible.
Les nested sets
Alors que les moteurs relationnels stockent des ensembles dans des tables spares, les
bases NoSQL ne grent pas de liens rfrentiels automatiques entre les donnes, mme si
rien ne les en empche. MongoDB, par exemple, inclut un type DBRef qui reprsente la
rfrence une cl dun autre document. Vous pouvez tout fait crer un code JavaScript
excut du ct serveur qui rcupre cette rfrence et ajoute son contenu dans le
document retourn. En revanche, il serait impossible par ce mcanisme dobtenir les
mmes performances que les jointures dun moteur relationnel, o les algorithmes de
jointure sont optimiss. La pratique dans un moteur NoSQL sera alors dinclure les sous-
ensembles de donnes dans lensemble parent, par exemple sous la forme densembles
embots (nested sets). Prenons un exemple trs simple de gestion de catgories de
produits. Si nous voulons exprimer une hirarchie de catgories de produits, nous pouvons
le faire dans une collection MongoDB en hirarchie pure, en indiquant par exemple un
niveau et la rfrence du parent :
db.categories.insert ({_id: vtements, parent: null, niveau: 0})

db.categories.insert ({_id: chaussures, parent: vtements, niveau: 1})


db.categories.insert ({_id: jupes, parent: vtements, niveau: 1})
db.categories.insert ({_id: salopettes, parent: vtements, niveau: 1})

db.categories.insert ({_id: sous-vtements, parent: vtements, niveau: 1})


db.categories.insert ({_id: culottes, parent: sous-vtements, niveau: 2})

Mais nous pouvons galement lexprimer dans lautre sens, en incluant une liste des sous-
lments, de la faon suivante :
db.categories.insert ({_id: vtements, descendants: [chaussures, jupes,
salopettes, sous-vtements], niveau: 0})

db.categories.insert ({_id: sous-vtements, descendants: [culottes, caleons,


soutien-gorge], niveau: 1})
db.categories.insert ({_id: caleons, descendants: [unis, caleons, soutien-

gorge], niveau: 1})

Ensuite, nous pouvons trouver la liste des catgories de niveau 1 (donc les descendants du
niveau 0) :
db.categories.findOne ({ niveau: 0}).descendants

Ce qui retourne les descendants sous forme de tableau, facile manipuler :


[chaussures, jupes, salopettes, sous-vtements]

Choisir larchitecture matrielle


linstar de la question de la modlisation des donnes, la problmatique de larchitecture
matrielle est moins importante en NoSQL que dans le domaine des moteurs relationnels.
Un moteur relationnel, consign sur une machine ou un petit nombre de nuds, a des
exigences plus fortes sur la qualit du matriel, le type de stockage mettre en uvre et
les moyens dassurer ventuellement la rplication de ce stockage dans un modle de
cluster. Dans le monde NoSQL, des moteurs comme Cassandra, Riak ou mme MongoDB
nont absolument pas ce type dexigence. Au contraire, ils sont conus pour tre
lgamment distribus sur des machines de puissance moyenne, remplaables et
interchangeables facilement, ce quon appelle du commodity hardware. L o un moteur
relationnel essaie doptimiser son rapport au matriel, travers des mcanismes internes
de gestion des processeurs, de la mmoire et du disque, les moteurs NoSQL comptent plus
sur une rpartition du travail sur des nuds qui individuellement nont pas besoin de
dgager une forte puissance, mais qui font la force par leur union. Tout cela obit un
principe dconomie propre aux ralits de linformatique daujourdhui : les machines de
moyenne puissance cotent peu cher et sont faciles remplacer. Quelques points sont
toutefois respecter.
Tout dabord, tous les moteurs peuvent profiter dune bonne quantit de RAM. Cassandra
et HBase conservent leurs donnes en mmoire dans un memstore, qui est rgulirement
purg sur le disque lorsquil est plein. Cassandra maintient en mmoire un cache de cls et
un cache de donnes. Pour ces deux outils, il est utile de surveiller et de paramtrer la
quantit de mmoire alloue pour obtenir les meilleures performances. En ce qui concerne
Cassandra, la quantit de mmoire ncessaire est lie au nombre de familles de colonnes
que vous dfinissez, puisque chaque famille de colonnes est maintenue dans un memstore.
Riak offre un choix de moteurs de stockage bas sur ce qui est disponible pour Erlang,
mais globalement, larchitecture est semblable : WAL et criture en RAM. MongoDB
place ses donnes en cache en utilisant les fonctions de cache de fichiers fournis par le
systme (par fichiers projets en mmoire laide de la fonction mmap). Ceux-ci travaillent
leurs donnes en RAM bien sr, et profitent de grandes quantits de mmoire,
spcialement lorsque le volume de donnes utiliser est important.
CouchDB
CouchDB est une exception, il peut se contenter de peu de mmoire car il nutilise aucune forme de cache en
interne, autre que celle propose nativement par le systme dexploitation. CouchDB est souvent utilis dans des
systmes embarqus.

Il est donc important de soigner la quantit de mmoire et de choisir un systme 64 bits,


afin de ne pas souffrir de la limite des 4 Go impose par le pointeur 32 bits. Il faut aussi
surveiller le swap sur le disque. En effet, si un moteur NoSQL voit son espace de travail
swapp cause dun manque de mmoire, les performances seffondreront.
Il peut tre utile galement de tester les performances de votre systme avec plus ou moins
de RAM. Pour cela, vous pouvez utiliser un outil trs simple, qui effectue une allocation
de mmoire de la taille dfinie en paramtre (avec un simple appel malloc()). Vous
trouverez cet utilitaire sur le dpt GitHub de MongoDB, ladresse suivante :
https://github.com/mongodb/mongo-snippets/blob/master/cpp/eatmem.cpp. Un outil
similaire pour Windows peut tre trouv dans cet article du MSDN Magazine :
http://msdn.microsoft.com/en-us/magazine/cc163613.aspx. Cela vous permettra de mieux
connatre vos besoins et de faire des tests de charge, ce qui est toujours trs important.
Nous en parlerons plus loin.

valuer les besoins en mmoire de Redis


videmment, la quantit de RAM est encore plus importante pour les bases de donnes en
mmoire comme Redis, Membase ou Couchbase. Riak offre galement un moteur de
stockage en mmoire, mais qui devrait tre rserv pour des tests.
Pour Riak, Basho propose un calculateur de quantit de RAM par rapport la taille de vos
donnes, si vous utilisez le systme de stockage Bitcast
(http://docs.basho.com/riak/1.1.0/references/appendices/Bitcask-Capacity-Planning/),
principalement parce que le stockage Bitcast implique que toutes les cls soient
maintenues en RAM. Nous reparlerons de Bitcast dans la section suivante ddie au
disque. Redis essaie dtre aussi efficient que possible dans sa consommation mmoire,
mais il ny a pas de miracle : toutes vos donnes doivent rsider en RAM. partir de la
version 2.6, un algorithme doptimisation de mmoire a t intgr au moteur, qui permet
de diminuer de faon consquente lempreinte en RAM des donnes. Pour plus de
renseignements, consultez la page web suivante : http://redis.io/topics/memory-
optimization.
Mmoire virtuelle en Redis
partir de la version 2, Redis a intgr un systme nomm mmoire virtuelle (virtual memory) qui permet de grer
en interne un systme de swap pour dplacer sur disque (idalement un SSD) les valeurs les moins utilises, toutes
les cls restant quant elles en mmoire. Ceci seffectue grce un algorithme bas sur le temps de dernier accs et
sur la taille des valeurs. Cette fonctionnalit a t dprcie et retire aprs la version 2.4.

Il nest forcment ais dvaluer la mmoire ncessaire pour Redis. La mthode la plus
simple consiste partir de la taille actuelle des donnes et calculer grossirement les
besoins en multipliant cette valeur avec le nombre dlments attendus. Pour afficher la
taille actuelle des donnes, vous pouvez utiliser la commande info :
redis-cli info

qui retourne sur notre serveur dexemple le rsultat suivant, dont nous navons conserv
que les informations relatives la mmoire :
# Memory
used_memory:4330248

used_memory_human:4.13M
used_memory_rss:5623808

used_memory_peak:4292720
used_memory_peak_human:4.09M

used_memory_lua:20480

mem_fragmentation_ratio:1.30
mem_allocator:jemalloc-3.0.0

# Keyspace
db0:keys=15174,expires=0

Ici, nous avons une consommation mmoire de 4,13 Mo pour 15 174 cls, qui comportent
des tweets. Il sagit de lapplication exemple que nous avons ralise au chapitre 10. Les
valeurs stockes ne sont pas trs volumineuses. Cela nous donne une ide du nombre de
valeurs que nous pouvons stocker avec notre quantit de mmoire. Cette occupation en
RAM peut faire rflchir sur la validit de lutilisation de Redis pour de larges volumes.
Ne dsesprez tout de mme pas trop vite. Il est possible de tricher un peu afin doptimiser
le stockage : profiter des tables de hachage, qui offrent un stockage optimis. Au lieu de
stocker vos cls indpendamment, vous pouvez regrouper des paquets de cls dans des
tables de hachage dont les cls correspondent aux valeurs de range. Vous pourrez ainsi
trouver rapidement la bonne cl pour ouvrir la bonne table de hachage qui contient la
donne que vous voulez utiliser. Thoriquement, vous pourriez mme utiliser un
algorithme bas sur du consistent hashing pour gnrer votre cl, ou essayer de travailler
avec un filtre de Bloom. Cette mthode permet dconomiser pas mal despace. Vous
trouverez une discussion sur cette technique sur le blog dInstagram, qui lutilise en
production : http://instagram-engineering.tumblr.com/post/12202313862/storing-
hundreds-of-millions-of-simple-key-value-pairs.
Attention aux sauvegardes sur disque
La mmoire occupe par Redis peut augmenter lors dune opration de sauvegarde sur disque, par exemple en
lanant la commande BGSAVE. Pour effectuer lopration, Redis lance un sous-processus en effectuant un fork, qui
va travailler sur un instantan (snapshot) des donnes. Les donnes entre les deux processus sont partages, sauf
celles qui sont crites pendant lexistence du sous-processus : linstantan devra se maintenir et ces donnes
modifies seront doubles en mmoire, lancienne version tant conserve pour le sous-processus. Sur un systme
qui gnre beaucoup dcritures, cela peut demander de la mmoire libre supplmentaire.

Pour connatre loccupation mmoire actuelle, nous pouvons utiliser la commande free :
free -mt

ce qui retourne chez nous :


total used free shared buffers cached

Mem: 977 893 84 0 54 48


-/+ buffers/cache: 790 187
Swap: 999 93 906

Total: 1977 986 991

Loption -m demande un retour en Mo, -t affiche un total. Nous avons donc ici 977 Mo de
RAM physique disponible. Nous ignorons les 999 Mo de swap, que nous ne voulons bien
sr pas utiliser.
Voyons maintenant, de lextrieur, quelle est la consommation mmoire de Redis :
ps aux | grep [r]edis-server

ce qui retourne chez nous :


rudi 4825 0.2 0.5 31612 5492 pts/2 Sl+ 15:46 0:33 redis-server

La commande ps
La commande ps retourne des informations sur les processus. Les options aux signifient, pour simplifier, voir les
dtails de tous les processus . Nous passons le rsultat de la commande loutil grep, qui ne garde que les lignes
qui nous intressent. Nous commenons le modle recherch par grep par des crochets ([]) autour de la premire
lettre, il sagit dun truc pour viter de retourner la commande dappel de ps aux | grep elle-mme. Sans cela,
nous aurions deux lignes : celle que nous cherchons, plus la commande que nous venons de lancer puisquelle
contient la chane redis-server . Comment cela fonctionne-t-il ? [] indique un intervalle de caractres, nous
cherchons donc un r suivi de edis-server . Nous ne trouvons pas la commande que nous lanons dans le
rsultat, puisque pour la trouver il faudrait maintenant chercher littralement la chane r]edis-server .

Le rsultat obtenu contient les colonnes suivantes :


USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND

Nous avons donc un pourcentage de mmoire utilise, chez nous 0,5, puis une valeur pour
VSZ (31612) et une valeur pour RSS (5492). Les rsultats sont exprims en octets. VSZ
signifie virtual set size et RSS resident set size, soit la taille alloue par le systme dans la
mmoire virtuelle et la taille occupe physiquement dans la RAM. Cette valeur comporte
les ventuelles bibliothques partages en mmoire avec dautres applications, elle nest
donc pas parfaite. Vous pouvez afficher plus prcisment la taille occupe en mmoire en
utilisant la commande pmap. Voici un exemple dappel pour Redis :
pmap -x $(pidof redis-server)

Nous rcuprons le PID (identifiant de processus) de redis-server et nous lutilisons pour


pmap. Loption -x affiche un rsultat tendu qui nous permet de voir le dtail. Voici quelques
lignes de rsultat :
4825: redis-server

Address Kbytes RSS Dirty Mode Mapping


08048000 0 392 0 r-x-- redis-server

080e7000 0 4 4 r---- redis-server

080e8000 0 12 12 rw--- redis-server

080eb000 0 40 40 rw--- [ anon ]


09e9a000 0 28 28 rw--- [ anon ]
b5400000 0 416 416 rw--- [ anon ]

b5bfe000 0 0 0 ----- [ anon ]


b5bff000 0 4 4 rw--- [ anon ]
b63ff000 0 0 0 ----- [ anon ]

b6400000 0 3872 3872 rw--- [ anon ]


b7601000 0 4 4 rw--- [ anon ]
b7602000 0 508 0 r-x-- libc-2.13.so


-------- ------- ------- ------- -------
total kB 31608 - - -

La valeur Dirty indique la valeur utilise en mmoire physique, non swappe.


Appel avec sudo
Si le processus sexcute avec un compte pour lequel vous navez pas de droit, vous devez lancer la commande
pmap avec sudo.

Nous navons conserv que quelques lignes du rsultat. Vous constatez que loccupation
est utilement spare entre le processus lui-mme, les bibliothques partages (qui
apparaissent sur plusieurs lignes car la zone mmoire utilise pour le code est spare de
la zone mmoire utilise pour les donnes), des sections marques Anon, qui indiquent des
blocs de mmoire rservs par une fonction malloc ou mmap, et la pile (stack, lendroit o son
stockes les variables locales du code). Cette vision vous sera utile si vous voulez analyser
plus prcisment loccupation mmoire de votre moteur.
Si vous voulez vraiment tous les dtails, vous pouvez utiliser la vision donne par le
fichier virtuel smaps dans le rpertoire /proc du processus. Nous avons vu prcdemment
que le PID de redis-server est 4825, nous pouvons donc inspecter ce fichier ainsi :
cat /proc/4825/smaps

La valeur Private_Dirty que nous trouverons dans ce fichier est lultime prcision que nous
pouvons obtenir sur lutilisation relle de la mmoire physique de chaque lment de notre
programme.
Nous sommes entrs un peu dans les dtails pour vous donner des outils gnriques afin
danalyser la consommation mmoire de nimporte quel processus, donc moteur NoSQL.
Chaque moteur peut toutefois publier ses propres informations, comme nous lavons vu
avec Redis.

valuer les besoins disque


Lvaluation des besoins disque nest pas forcment aise non plus. Les moteurs orients
documents peuvent consommer beaucoup plus despace disque que les moteurs
relationnels, cause de la redondance des donnes dans leur modle.
CouchDB est particulirement gourmand cet gard, pour plusieurs raisons.
Il maintient plusieurs versions du mme document JSON. Il faut donc effectuer des
compactages rguliers.
La cration de vues gnre des index, donc des structures redondantes, qui sont
persistes sur disque. Ces index doivent se maintenir, au dtriment de lespace disque.
Les vues doivent aussi tre compactes.
Lorsque les vues sont modifies, danciens index peuvent rester sur le disque. Une
commande existe pour le nettoyage : _view_cleanup.
Les diffrentes options de compactage sont documentes ladresse suivante :
http://wiki.apache.org/couchdb/Compaction.

MongoDB
En MongoDB, les fichiers sont prallous avec des tailles fixes. Lorsque les fichiers
atteignent une taille de 2 Go, les prochaines prallocations de fichiers seffectuent par
incrments de 2 Go. Un certain nombre de commandes permettent de dterminer la taille
relle des donnes. En voici un exemple pour notre collection articles :
db.articles.dataSize(); // taille des donnes
db.articles.totalIndexSize(); // taille des index

db.articles.storageSize(); // allocation, comporte lespace inutilis

db.articles.totalSize(); // donnes et index

Cassandra
Les moteurs orients colonnes comme Cassandra utilisent un schma de stockage proche
de celui des moteurs relationnels, avec des critures squentielles dans un journal puis,
rgulirement, une criture squentielle en masse dans un fichier immutable (chaque
famille de colonnes est stocke dans un fichier distinct), en mode append. Ce mcanisme
limite au maximum les besoins de lectures alatoires qui, rappelons-le, sont les points
faibles des disques magntiques. Le temps moyen daccs en lecture alatoire sur un
disque magntique est de 10 ms au moins. Connaissant cela, les quelques rgles de base
pour organiser le sous-systme disque de serveurs faisant tourner Cassandra sont assez
videntes.
Privilgier les disques avec de bons rendements en lecture mais aussi en criture.
Le SSD peut tre une solution, mais il faut quil ait un bon ratio criture/lecture.
Compte tenu des besoins de stockage, gnralement levs, des bases Cassandra (nous
voluons en gnral dans du Big Data), il est prfrable de ne pas dpenser en SSD et de
se contenter de disques de performances moyennes, mais de distribuer la charge sur
plusieurs machines, ce pourquoi Cassandra est conu en premier lieu.
Sparer le disque de journal (commitlog) du disque contenant les donnes (SSTable).
Privilgier le RAID 10 au RAID 5, qui est lent en criture cause du calcul de parit.
Formater les disques avec un systme de fichiers moderne comme ext4 ou XFS. La
limite de taille dun fichier en ext3 est de 2 To alors que ext4 supporte des fichiers de 16
To. Les fichiers de Cassandra peuvent atteindre de grandes tailles. De plus, les
performances de suppression de fichiers de grande taille sont bien meilleures en ext4
quen ext3, ce qui est bnfique lors des phases de compactage.
Il est noter que les fichiers de donnes (SSTable) de Cassandra tant immutables, ils
saccumulent pour une mme famille de colonnes. Rgulirement, Cassandra va les
fusionner et les compacter (regrouper les fichiers, nettoyer les lignes marques en
tombstone, etc.). Ceci implique deux choses : un pic dactivit disque ce moment et un
besoin despace libre souvent consquent. Pour viter les problmes, il peut tre
ncessaire de laisser 50 % despace disque libre sur vos partitions contenant les SSTable
de Cassandra.
Leveled compaction
Le mode de compactage utilis par dfaut dans Cassandra (nomm tiered compaction) peut ncessiter dans le pire
des cas le double despace de stockage. Depuis Cassandra 1.0, vous pouvez configurer vos familles de colonnes
pour utiliser un mode de compactage beaucoup moins gourmand (environ 10 % despace libre ncessaire par
rapport au volume des donnes). Ce mode de compactage est appel leveled compaction. Il est document sur la
page web suivante : http://www.datastax.com/dev/blog/when-to-use-leveled-compaction.

Riak
Riak, de son ct, peut utiliser diffrents moteurs de stockage qui sont en fait des API de
srialisation disponibles en Erlang. Le moteur le plus utilis est Bitcast, qui est structur
autour dune table de hachage journalise et optimise pour stocker les paires cl-valeur.
Riak cre un rpertoire Bitcast par vnode. Pour viter des accs disque alatoires, Riak
crit autant que possible ses fichiers en mode append-only, ce qui peut provoquer une
augmentation de la taille des rpertoires cause de la prsence de donnes dupliques.
Lorsque la limite despace disque dfinie est atteinte, Riak opre un compactage en
crivant un nouveau fichier de donnes. Vous pouvez paramtrer la taille maximale de vos
fichiers, les priodes pendant lesquelles un compactage (merge) peut tre effectu par
Riak, et quelles sont les conditions de dclenchement de ce compactage. Les dtails sont
disponibles sur cette page : http://docs.basho.com/riak/latest/tutorials/choosing-a-
backend/Bitcask/. En rsum, une fois de plus il faut prfrer des disques de bonne taille,
avec de bonnes performances en criture. vitez vraiment le RAID 5.

Virtualisation
Bien entendu, les moteurs NoSQL peuvent tre installs dans des machines virtuelles,
comme celles gres par VMWare ESX, ou Xen. Une machine virtuelle offre moins de
performances quune machine physique, et cela peut se ressentir plus spcialement dans
les moteurs qui font une utilisation intensive du matriel. Un moteur, relationnel ou
NoSQL, est souvent fortement sollicit. Si cest le cas, essayez de le faire tourner sur une
machine physique ou au moins soignez la configuration de votre machine virtuelle en ce
qui concerne les accs disque et la gestion de la mmoire, qui sont les deux lments
importants dans un moteur de bases de donnes (tout ce qui touche aux entres/sorties).
Sur VMWare ESX, deux lments au moins sont prendre en compte. Tout dabord,
VMWare offre une fonctionnalit de partage de la mmoire entre les VM, nomme
overcommit. Elle consiste donner une machine virtuelle de la mmoire normalement
rserve pour une autre qui ne lutilise pas. Cette fonctionnalit doit tre utilise avec
prudence, certains utilisateurs ont en effet rencontr des problmes avec des moteurs
comme Cassandra ou MongoDB. De toute manire, un serveur de bases de donnes fait
souvent un usage intensif de la mmoire pour son cache, dans ce cas, lovercommit est
moins intressant.
Ensuite, surveillez bien les performances des disques et assurez-vous que la configuration
est correcte. Par exemple, chez un de nos clients, nous avons expriment de trs
mauvaises performances sur un SAN cause du paramtre daccs multichemin
(multipathing) dfini dans VMWare. Celui-ci tait configur en Circulaire (Round-Robin).
Aprs lavoir pass en fixe, le temps de copie dun fichier de 800 Mo est pass de 3 min
40 s. a environ 10 s
Pour ce qui est des serveurs qui ne travaillent pas beaucoup (par exemple, des serveurs de
configuration dune installation sharde de MongoDB), il est bien sr intressant de les
virtualiser.

Mettre en place la solution et importer les donnes


Comment sassurer dune bonne installation ? Importer et convertir les donnes existantes
pour les intgrer dans une base NoSQL ?

Dploiement distribu
Le dploiement est compltement diffrent selon que vous installez une base de donnes
en mmoire comme Redis ou un moteur distribu comme Cassandra ou HBase. Il ny a
rien de particulier dire sur le dploiement de solutions monoserveurs, nous allons donc
aborder le dploiement distribu.
Si vous devez mettre en place quelques serveurs, une approche base sur des scripts shell
sur un systme Unix, ou Powershell pour Windows peut tre suffisante. Dans le monde
Unix, utilisez des scripts shell dploys par ssh, qui permet non seulement douvrir une
session interactive sur une machine distante travers une connexion scurise, mais aussi
dexcuter une commande directement en la mentionnant comme paramtre de lappel
ssh. En voici un exemple :

ssh rudi@carthage.babaluga.com df -h

Ici, nous excutons directement la commande df h. Elle retourne lespace libre sur les
disques de la machine avec un affichage ais lire (grce loption -h) sur le serveur
carthage.babaluga.com en sidentifiant comme utilisateur rudi. Cette commande peut tre
simplifie encore en utilisant un alias ou un script shell. En utilisant le shell bash, nous
pouvons ajouter cette ligne dans notre fichier ~/.bashrc :
alias carthage=ssh rudi@carthage.babaluga.com

Il nous suffira alors de lancer notre commande ainsi :


carthage df -h

pour obtenir le mme rsultat. Il est ensuite ais de boucler sur plusieurs serveurs, comme
dans lexemple suivant :
for i in 192.168.0.22 192.168.0.100; do

ssh rudi@$i df -h

done

qui lance la commande df -h sur les machines accessibles sur les adresses IP 192.168.0.22
et 192.168.0.100 avec le compte rudi.
Authentification par cl
videmment, pour rendre cette mthode utile en pratique, nous avons d au pralable configurer une scurit base
sur une paire de cls. Dans le cas contraire, il aurait fallu entrer notre mot de passe (celui du compte rudi) chaque
tentative de connexion. La configuration dune authentification ssh par cl dpasse le cadre de cet ouvrage. Pour
une description claire de la marche suivre, consultez la page suivante : http://doc.ubuntu-
fr.org/ssh#authentification_par_un_systeme_de_cles_publiqueprivee.

Notons que lun des problmes de cette approche apparat avec des commandes plus
complexes : la gestion des apostrophes pour protger une chane peut savrer
cauchemardesque et elle est assez mal supporte selon les systmes.
De la mme faon, nous pouvons copier des fichiers sur les diffrents serveurs laide de
scp.

scp ~/cassandra/cassandra.yaml rudi@carthage.babaluga.com:/etc/cassandra/cassandra.yaml

La commande scp copie le fichier de configuration cassandra.yaml situ sur la machine locale
vers le rpertoire distant /etc/cassandra/. Cette approche est elle aussi assez frustre, elle ne
fonctionne que par remplacement de tout le fichier. Bien entendu, des commandes sed
peuvent tre envoyes vers les machines distantes pour effectuer les remplacements, et
cest parfaitement envisageable dans de petits environnements. Il y a aussi quelques
initiatives qui permettent de pousser un peu plus lutilisation de ssh. Ainsi, les outils
parallel-ssh (http://code.google.com/p/parallel-ssh/) en Python et ClusterSSH
(http://sourceforge.net/apps/mediawiki/clusterssh/) en Perl peuvent tre utiliss en tant que
bibliothques dans leur langage respectif pour crer des scripts plus complexes. Citons
galement PyDSH (http://pydsh.sourceforge.net/index.php), un shell distant crit en
Python. Il est aussi possible dutiliser un gestionnaire de codes sources distribu comme
git, ce qui prsente lavantage de maintenir aussi les versions des fichiers de configuration.
On peut tirer rgulirement les modifications depuis les machines en planifiant une
commande git pull via cron.
Des outils de gestion de configuration distribue libres ont fait leurs preuves et sont
quasiment indispensables lorsque le parc de machines atteint un certain seuil. Les deux
outils les plus utiliss sont CFEngine et Puppet.

Outils de gestion de configuration


CFEngine et Puppet, bien que rpondant des besoins similaires, sont des outils assez
diffrents. CFEngine est dvelopp en C et interprte un langage dclaratif qui dcrit ltat
du systme installer. Sa conception est base sur la thorie des promesses (promise
theory), cest--dire un modle multi-agent o chacun publie ses intentions sous forme de
promesses. Ceci constitue une base thorique la gestion base sur les stratgies (Policy
Based Management), mais en instillant lide dagents autonomes plutt que de machines
forces par des obligations. partir de ce principe, chaque machine conserve une certaine
autonomie. Un serveur centralis stocke les stratgies, qui sont distribues sur les htes, ce
qui permet CFEngine dappliquer les rgles sans se rfrer au serveur matre. CFEngine
assure galement une rcupration des erreurs et des changements de configuration. En
dautres termes, si une mise jour du systme ou des changements manuels troublent la
configuration telle que dcrite dans CFEngine, celui-ci sera capable de corriger la
diffrence et de revenir ltat souhait. De plus, le modle de CFEngine est relativement
dcentralis : chaque machine excute un dmon qui agit indpendamment des autres. De
ce point de vue, CFEngine est bas sur un modle similaire aux moteurs NoSQL
dcentraliss comme Cassandra ou Riak.
Sa prise en main est moins aise que Puppet, mais la phase dapprentissage en vaut la
peine. Comme sa mise en uvre est complexe, nous nallons pas en parler dans ce livre, il
faudrait lui consacrer un chapitre part entire. Sachez simplement quune interface web
pour CFEngine nomme Rudder est dveloppe par Normation
(http://www.normation.com/). Par ailleurs, si vous vous dcidez utiliser CFEngine
srieusement pour votre administration, nous vous recommandons la lecture du livre
Automating Linux and UNIX System Administration, de Nathan Campi et Kirk Bauer, paru
aux ditions Apress.

Importer les donnes


Chaque moteur comporte ses propres outils pour importer et parfois exporter des fichiers
plats, comme du CSV (donnes spares par des virgules), afin de raliser des transferts de
donnes en masse. La plupart du temps, vous naurez pas dvelopper une routine vous-
mme. CouchDB reprsente une exception car il ne propose pas doutil dimport-export.
Pour importer vos donnes, vous devrez crire du code. Pour ce qui est de lexportation,
vous pourrez crer ce que CouchDB appelle une fonction de liste, qui permet de montrer
les donnes dans le format que vous souhaitez. Pour plus dinformations, consultez cette
page de documentation : http://guide.couchdb.org/editions/1/en/transforming.html.

MongoDB
MongoDB propose deux outils en ligne de commande pour effectuer des imports et des
exports de fichiers au format JSON ou CSV. Notez que le format de stockage MongoDB
(BSON) comporte des types lgrement diffrents du JSON originel ; vous pouvez donc
rencontrer des diffrences entre le JSON gnr et les donnes stockes. La liste des
diffrences est disponible ladresse suivante :
http://docs.mongodb.org/manual/administration/import-export/.
Voici quelques exemples dexports :
mongoexport --db passerelles --collection articles --out ~/passerelles.articles.json

mongoexport --db passerelles --collection articles --jsonArray --out ~/passerelles.


articles.json

mongoexport --db passerelles --collection articles --query { "auteur.nom" :


"Brizard"} --out ~/passerelles.articles.brizard.json
mongoexport --db passerelles --collection articles --csv --out ~/passerelles.articles.

csv --fields=auteur.nom,auteur.e-mail

La premire commande exporte la collection articles de la base passerelles dans un seul


fichier JSON. La deuxime fait de mme mais gnre un fichier contenant un tableau de
documents JSON. La troisime filtre les donnes pour nexporter que les documents o le
nom de lauteur est Brizard. Enfin, la dernire commande exporte le nom et le-mail de
lauteur dans un fichier spar par des virgules, dont nous reproduisons le contenu ci-
aprs.
auteur.nom,auteur.e-mail

"Brizard","annie.brizard@cocomail.com"
"Brizard","annie.brizard@cocomail.com"

Vous noterez quune ligne den-tte avec le nom des colonnes a t ajoute par mongoexport.
Voici un exemple dimport de ce fichier CSV dans une nouvelle collection auteurs, qui sera
automatiquement cre limport :
mongoimport --db passerelles --collection auteurs --type csv --file ~/passerelles.
articles.csv headerline

Une notification nous indique que trois lignes ont t importes. La ligne den-tte est
compte dans limport, mais ne vous inquitez pas, grce loption headerline, elle ne sera
pas considre comme une ligne de donnes. Voyons le contenu de notre collection dans
linvite mongo :
> use passerelles;
switched to db passerelles
> db.auteurs.find();

{"_id" : ObjectId("50e2e278b95794cfad02012e"), "auteur.nom" : "Brizard", "auteur.e-


mail" : "annie.brizard@cocomail.com"} {"_id" : ObjectId("50e2e278b95794cfad02012f"),

"auteur.nom" : "Brizard", "auteur.e-mail" : "annie.brizard@cocomail.com"}

Comme vous pouvez le constater, partir dun import CSV, MongoDB cre une structure
BSON plate, non hirarchique : la liste auteurs na pas t recre.

Riak
Limport et lexport natifs en Riak sappuient sur des fonctions Erlang qui ont t
implmentes dans les modules bucket_importer et bucket_exporter. Pour consulter le code
source de ces fonctions, consultez les adresses suivantes :
http://contrib.basho.com/bucket_importer.html et
http://contrib.basho.com/bucket_exporter.html. Les modules dvelopps permettent de
dfinir un rpertoire contenant des fichiers JSON pour les importer dans Riak. Pour des
besoins plus prcis, vous devrez dvelopper les routines vous-mme.
Redis
Redis ne comporte pas doutil interne pour limportation de fichiers CSV. Plusieurs
techniques peuvent tre dployes pour effectuer une insertion en masse. Limportant est
dviter deffectuer une importation en boucle avec des instructions uniques, surtout si
vous accdez au serveur Redis travers le rseau. Dsormais, Redis permet le pipelining
de commandes, cest--dire lenvoi dun batch de commandes en un seul appel, soit avec
les commandes MULTI / EXEC, soit avec la fonctionnalit de pipelining de votre bibliothque
cliente. Voici un extrait de code Python utilisant le client Redis :
pipe = r.pipeline(transaction=False)

pipe.sadd(cle, valeur)


pipe.execute()

Nous ne dvelopperons pas davantage cet exemple, car nous utiliserons ce code dans
ltude de cas du chapitre 16. Reportez-vous ce chapitre pour un exemple complet.
En ligne de commande, vous pouvez utiliser le client Redis avec loption --pipe qui dfinit
un mode pipe relativement nouveau en Redis, disponible depuis la version 2.4. Lide est
de recevoir dans un pipe une liste de commandes Redis excuter en batch. Ces
commandes doivent tre crites dans un format spcial, le protocole Redis, et non pas en
texte simple, sinon le mode pipe ne pourra pas reconnatre les commandes. Ce protocole
est simplement constitu de la longueur de la chane suivie de la chane elle-mme aprs
un CRLF, avec quelques caractres supplmentaires. La page de documentation de Redis
(http://redis.io/topics/mass-insert) explique le protocole et offre une fonction Ruby pour
gnrer les commandes dans ce protocole. Il est ais de porter la fonction en Python, ce
que nous avons fait en lencapsulant dans un code qui prend en entre un fichier contenant
les commandes au format texte et qui retourne ces commandes dans le protocole Redis
pour tre utilises directement en pipe avec redis-cli. Voici le code Python du fichier que
nous avons appel redis-import.py :
#!/usr/bin/python

import sys, re
def redis_proto(ligne):

mots = ligne.split()

proto = * + str(len(mots)) + \r\n


for mot in mots:

proto += $ + str(len(mot)) + \r\n + str(mot) + \r\n

return proto
with open(sys.argv[1], r) as fichier:

for ligne in fichier:

sys.stdout.write(redis_proto(ligne))

Crons maintenant un fichier texte contenant des commandes Redis, nomm import-
redis.txt. Il est compos des lignes suivantes :

SELECT 1
SET 001 caillou

SET 002 hibou


SET 003 chou

SET 004 genou

Si nous appelons notre script avec notre fichier en entre, comme ceci :
python redis-import.py import-redis.txt

voici le dbut de ce quil nous retourne sur la sortie standard (STDOUT) :


*2

$6

SELECT
$1

*3
$3

SET
$3
001

$7
caillou

Ensuite, excutons limport en passant ce rsultat redis-cli :


python redis-import.py import-redis.txt | redis-cli --pipe

Redis nous rpond :


All data transferred. Waiting for the last reply
Last reply received from server.

errors: 0, replies: 5

Nos donnes sont bien intgres dans la base de donnes 1, nous pouvons le vrifier dans
redis-cli :

>select 1

OK

[1]> dbsize
(integer) 4

[1]> GET 002

"hibou"

Importer nos donnes dans Redis ncessite donc un peu de programmation, mais cest
assez ais et efficace.

Cassandra
Cassandra propose plusieurs outils pour raliser des imports et des exports. Le plus simple
consiste faire appel des commandes CQL cres sur le modle de commandes
PostgreSQL : COPY FROM et COPY TO. La commande suivante, saisie dans une session cqlsh,
exporte le contenu de la famille de colonnes articles dans un fichier articles.txt situ dans
le rpertoire personnel de lutilisateur, en sparant les colonnes par une barre verticale, et
en ajoutant en premire ligne le nom des colonnes :
COPY articles (KEY, auteur_email, auteur_nom, auteur_prenom, titre) TO ~/articles.

txt WITH DELIMITER = | AND QUOTE = AND ESCAPE = AND NULL = <null> AND
HEADER = true;

La commande suivante rimporte le mme fichier dans une famille de colonnes nomme
articles_import, que nous devons crer au pralable :

create table articles_import (KEY varchar PRIMARY KEY);


COPY articles_import (KEY, auteur_email, auteur_nom, auteur_prenom, titre) FROM ~/

articles.txt WITH DELIMITER = | AND QUOTE = AND ESCAPE = AND HEADER =

true;

NULL
Notez que loption NULL nest pas reconnue dans le COPY FROM. Linconvnient de cette mthode est quen prsence
de <null>, la colonne se crera quand mme et stockera la valeur de chane <null> .

Vous pouvez obtenir de laide sur ces commandes en tapant ceci dans une session cqlsh :
help copy;

Les utilitaires sstable2json et json2sstable permettent dexporter une famille de colonnes


contenue dans une SSTable vers un document JSON, et inversement. Son appel est trs
simple.
Un outil nomm sstableloader vous permet galement de raliser des imports et des exports
partir de SStable. Il ncessite un peu de dveloppement.

Avec du code utilisant Python


Voyons maintenant une mthode gnrique implmente dans du code Python. Pour
exemple, nous allons insrer le contenu de ce petit fichier CSV, nomm import-redis.csv :
userid;nom;prenom;email

001;bruchez;rudi;rudi@babaluga.com
002;dupuis;sidonie;sidonie@aglae.com

dans une base Redis, laide de ce script Python, que nous sauvegardons dans le fichier
import-csv.py :

#!/bin/python

import csv, redis

r = redis.StrictRedis(host=localhost, port=6379, db=2)


with open("import-redis.csv", "rb") as f:

for ligne in csv.DictReader(f, delimiter=;, quoting = csv.QUOTE_NONE):

r.hmset("user:%s" % ligne["userid"], {"nom":ligne["nom"],


"prenom":ligne["prenom"], "email":ligne["email"]})

Ici, nous ouvrons une connexion la base 2 de notre serveur Redis, puis nous utilisons le
module csv de Python pour stocker le contenu du fichier CSV dans un dictionnaire. Nous
insrons ensuite chaque ligne dans une table de hachage Redis laide de la commande
hmset, qui nous permet de gnrer la table de hachage en un seul appel. Ce code est fourni
comme exemple simple, il nest certainement pas trs rapide. Par exemple, il vaudra
mieux en cas de volume important utiliser du pipelining et rcuprer les lignes de csv en
utilisant la fonction csv.reader() qui stocke les colonnes dans une liste au lieu de crer un
dictionnaire. Vous pouvez trouver un didacticiel trs clair sur le module csv de Python
cette adresse : http://www.chicoree.fr/w/Fichiers_CSV_en_Python. Notez galement que
si vous dveloppez en Ruby, le module FasterCSV est prfrer au module csv de la
bibliothque standard.
Nous excutons notre code :
python import-csv.py

Il nous reste vrifier la prsence de nos deux lignes avec redis-cli :


redis 127.0.0.1:6379> select 2

OK

redis 127.0.0.1:6379[2]> dbsize


(integer) 2

redis 127.0.0.1:6379[2]> hmget user:001


(error) ERR wrong number of arguments for hmget command

redis 127.0.0.1:6379[2]> hgetall user:001


1) "nom"
2) "bruchez"

3) "prenom"
4) "rudi"
5) "email"

6) "rudi@babaluga.com"

Importer du XML
Gnralement, les moteurs NoSQL ne comportent pas doutil intgr qui permet les
changes de donnes, comme les outils ETL (Extract Tranform Load) du monde
dcisionnel. Comme vous lavez dj compris, il faut crire du code. Cest aussi le cas
pour importer des documents XML dans les moteurs orients documents. Grce aux
bibliothques prsentes dans les langages pour traiter facilement du XML, ce sera une
tche aise. Nous prenons ici un court exemple avec Python et MongoDB. Python est une
fois de plus un excellent langage pour ce genre de choses, car un grand nombre de
bibliothques existent pour manipuler des structures de donnes dans lesprit de Python.
Nous allons utiliser ici le module xmltodict qui, comme son nom lindique, permet de
transformer un document XML en dictionnaire Python. Cela tombe bien, puisque les
mthodes dinsertion de documents du pilote pymongo utilisent des dictionnaires Python
pour les transformer en interne en BSON. Lopration devient alors trs simple : il nous
suffit de passer le XML dans notre module et denvoyer le rsultat pymongo. Tout dabord,
nous installons xmltodict :
~/python_env/nosql/bin/pip install xmltodict

Le code de notre script est ensuite le suivant. Lide tant de rcuprer un document XML,
nous avons choisi le flux RSS du site dinformation de France Info, dont ladresse est
http://www.franceinfo.fr/rss/tag/1.
#!/usr/bin/python
# coding=utf-8

import urllib
import xmltodict

import pymongo
from pymongo import Connection

from pymongo.errors import ConnectionFailure


rss = http://www.franceinfo.fr/rss/tag/1
document = urllib.urlopen(rss)

o = xmltodict.parse(document)

try:
cn = Connection(host="localhost", port=27017)

print "connexion russie"

except ConnectionFailure, e:
sys.stderr.write("Erreur de connexion MongoDB: %s" % e)

sys.exit(1)
db = cn["france_info"]

assert db.connection == cn
print "handle acquis avec succs"
db.actus.insert(o, safe=True)

Nous utilisons dabord le module urllib pour accder au lien et rcuprer le document, que
nous transformons en dictionnaire laide de xmltodict.parse(). Nous initions ensuite une
connexion MongoDB et nous insrons simplement ce dictionnaire dans une collection
nomme actus de la base de donnes france_info. Voil, rien de plus simple. Si nous
enlevions la gestion des erreurs et si nous simplifiions le code, il pourrait tenir en quelques
lignes.
Il nous reste constater, dans le shell de MongoDB, que les donnes sont bien insres
dans la collection :
use france_info
db.actus.find()

Voici un extrait format du rsultat :


{
"title" : "Paso: famille, je vous \"aide\"",

"link" : "http://www.franceinfo.fr/actu/initiative-france-info/

paseo-famille-je-vous-aide-831091-2012-12-13",
"description" : "Pour allger le quotidien parfois pesant des familles

modestes, Nmes, lassociation Paso reprend un concept vieux dune

quarantaine dannes en Grande Bretagne. Des parents bnvoles viennent


donner un coup de main une fois par semaine gratuitement aux foyers qui en

ont le plus besoin.",

"category" : [{"@domain" : "http://www.franceinfo.fr/actu", "#text" :


"Actu"},

{"@domain" : "http://www.franceinfo.fr/economie", "#text" : "conomie"}],

"pubDate" : "Thu, 13 Dec 2012 06:20:00 +0100",


"dc:creator" : "Lucie Montchovi"

}
Un autre exemple dimport de XML dans MongoDB en utilisant C# est disponible cette
adresse : http://loosexaml.wordpress.com/2011/12/29/loading-xml-into-mongodb/.

Exemples de dveloppements
Pour vous aider dvelopper avec les moteurs NoSQL, de nombreuses applications de
dmonstration en source libre sont votre disposition. Nhsitez pas vous plonger dans
leur code pour vous inspirer. Voici quelques exemples :
La distribution de Cassandra par DataStax comporte une application dexemple en Java,
nomme Portfolio Manager, qui utilise le pilote JDBC du langage CQL. Vous en trouvez
un descriptif cette adresse :
http://www.datastax.com/docs/1.0/getting_started/dsc_demo ;
Twissandra est une application similaire Twitter, utilisant Cassandra comme moteur de
bases de donnes. Vous pouvez la tester sur http://twissandra.com/. Malgr son interface
un peu spartiate, les fonctionnalits sont basiquement semblables Twitter. Les codes
sources de cette application sont disponibles ladresse suivante :
https://github.com/twissandra/twissandra ;
Des programmes de dmonstration semblables existent pour Redis, disponibles
ladresse suivante : http://redis.io/topics/twitter-clone. Vous y trouverez notamment
lapplication originale en PHP (retwis), ainsi quune implmentation en Ruby avec le
framework Sinatra et en Java avec Spring. Notez que les commandes de Redis peuvent
voluer au fil des versions, et que le code dexemple peut ne pas toujours reflter la
manire la plus efficace de manipuler les donnes Redis lheure actuelle ;
Un autre exemple intressant dapplication base sur Redis est haplocheirus
(https://github.com/twitter/haplocheirus), un systme de gestion de timelines (lignes de
temps). Lun des intrts de ce projet est quil ajoute une couche de sharding de la base
Redis sur plusieurs nuds en utilisant gizzard (https://github.com/twitter/gizzard), une
bibliothque qui rpartit les donnes entre le client et le serveur ;
NodeCellar (http://nodecellar.coenraets.org/) est une application dexemple utilisant
NodeJS avec MongoDB comme moteur de donnes. Comme son nom lindique, il sagit
dune application de gestion de caves vin. Le code source est disponible sur GitHub :
https://github.com/ccoenraets/nodecellar ;
En ce qui concerne Riak, une liste de petites applications dexemples est disponible sur
le site de Basho :
http://docs.basho.com/riak/1.3.0/references/appendices/community/Sample-
Applications/ ;
Enfin, nous avons dj mentionn lapplication Sofa, dveloppe pour le livre CouchDB:
The Definitive Guide. Il sagit dune application de blog totalement dveloppe en
CouchDB en utilisant CouchApp. Son code source est disponible ladresse suivante :
https://github.com/jchris/sofa.
15
Maintenir et superviser ses bases NoSQL

Les moteurs NoSQL sont, au mme titre que les moteurs relationnels, des applications
serveur. Ils rpondent de manire centralise des requtes clientes, et sont de ce fait des
applications centrales et dcisives pour le bon fonctionnement des applications. Il est
important dassurer une supervision srieuse des serveurs et de leurs performances. Nous
allons voir dans ce chapitre quelques lments de supervision et danalyse propres aux
moteurs NoSQL.

Raliser des tests de charge


Dans le domaine des applications utilisant une base de donnes, il est trs important de
raliser des tests de charge de manire savoir quel est le nombre dutilisateurs et le
volume de donnes quest capable de supporter un serveur. Traditionnellement, les
applications utilisant des moteurs relationnels sont dveloppes avec des bases de donnes
de test qui sont peu volumineuses. Bien entendu, lapplication est dveloppe dans un
contexte peu concurrentiel, o seuls quelques dveloppeurs accdent la base. Dans ces
conditions, il est impossible de dtecter les points de ralentissement durant la phase de
conception. La volumtrie voluant et le nombre daccs simultans se multipliant, les
gros problmes de performances apparaissent au plus mauvais moment, lorsque la solution
est en production et durant les pics dactivit o lentreprise fonctionne plein rgime. La
catastrophe nest pas loin.
Thoriquement, les moteurs NoSQL sont plus souples ce niveau : HBase, Cassandra,
Riak et MongoDB sont capables de monter en charge horizontalement et automatiquement
par lajout de machines dans le cluster. Pour supporter un pic dactivit, il suffit donc
dajouter de nouvelles machines. Dans la pratique, il est utile et important de raliser des
tests de charge pour savoir combien dutilisateurs un nud est capable de supporter et
ainsi pouvoir planifier une capacit par machine, et donc la taille du cluster. De plus, dans
le cas de moteurs comme Redis, o le but est doffrir de la rapidit sur une seule machine,
la problmatique se pose comme dans le cas des moteurs relationnels.
Les tests de charge comportent deux aspects : ajouter des donnes en masse pour
augmenter la volumtrie, et simuler un grand nombre dutilisateurs pour tester les
capacits de concurrence. Le premier aspect nest pas compliqu, il faut dvelopper
spcifiquement du code qui va alimenter lentrept avec des donnes de test, laide de
boucles. Lexemple du chapitre 10 qui consistait rcuprer des donnes de Twitter pour
les insrer dans Redis est un exemple de code permettant de gnrer du volume.
Les imports et les exports
Noubliez pas de tester votre systme NoSQL avec des imports ou des exports de donnes si vous devez en faire,
car ce sont des oprations qui peuvent consommer beaucoup de RAM.

Redis
Certains moteurs livrent des outils de benchmarking, cest notamment le cas de Redis.
Loutil sappelle redis-benchmark, il permet de simuler des GET et des SET envoys par un
certain nombre dutilisateurs simultans. Voici un exemple dappel :
redis-benchmark -q -n 100000 -d 2000 -k 0

Les options de la commande sont les suivantes :


-q (quiet) : naffiche que les informations importantes ;
-n 100000 : nombre de requtes envoyer ;
-d 2000 : taille des donnes envoyes par les GET et SET en octets, par dfaut 2 octets ;
-k 0 : force les reconnexions, sinon la connexion reste en keep alive.
La commande peut chouer si le systme dexploitation a dsactiv la fonctionnalit de
keep alive. Dans ce cas, la pile rseau ne pourra pas crer le nombre de connexions
demandes avec assez de clrit. redis-benchmark affichera probablement ce message :
WARNING: keepalive disabled, you probably need echo 1 > /proc/sys/net/ipv4/tcp_tw_

reuse for Linux and sudo sysctl -w net.inet.tcp.msl=1000 for Mac OS X in order to
use a lot of clients/requests.

Sur Linux, nous avons donc activ la fonctionnalit tcp_tw_reuse laide de la commande
suivante, excute en tant que root.
echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse

puis nous avons lanc la commande. Aprs un certain temps dexcution, voici le rsultat
final :
PING_INLINE: 7962.42 requests per second

PING_BULK: 7968.76 requests per second


SET: 6529.55 requests per second

GET: 6578.08 requests per second

INCR: 7908.89 requests per second


LPUSH: 5566.69 requests per second

LPOP: 5339.88 requests per second

SADD: 7158.71 requests per second


SPOP: 7866.58 requests per second

LPUSH (needed to benchmark LRANGE): 6118.45 requests per second

LRANGE_100 (first 100 elements): 1565.14 requests per second


LRANGE_300 (first 300 elements): 568.47 requests per second

LRANGE_500 (first 450 elements): 378.38 requests per second

LRANGE_600 (first 600 elements): 282.54 requests per second


MSET (10 keys): 4092.32 requests per second

Nous obtenons un nombre doprations par seconde, qui correspond ici notre machine
virtuelle avec un processeur cadenc 3,1 GHZ et avec 1 Go de RAM.
Cassandra
Cassandra est galement livr avec un outil de test de charge, crit en Java et nomm
cassandra-stress. La liste des options est disponible dans la documentation ladresse
suivante : http://www.datastax.com/docs/1.1/references/stress_java. Il y a quelques options
intressantes, notamment :
--enable-cql : permet de tester les requtes en CQL plutt quen langage natif, on peut
ainsi voir les diffrences de performance ;
--nodes : liste de nuds sur lesquels il est possible deffectuer le test ;
--threads : nombre de threads excuter, 50 par dfaut.
Sur notre systme, nous avons lanc cassandra-stress avec les options par dfaut. Voici
quelques lignes du rsultat :
Created keyspaces. Sleeping 1s for propagation.
total,interval_op_rate,interval_key_rate,avg_latency,elapsed_time
8124,812,812,0.05000036927621861,10

20162,1203,1203,0.036634906130586474,20
35208,1504,1504,0.0280090389472285,30
54869,1966,1966,0.01964879711103199,40

73493,1862,1862,0.019572594501718214,50
93131,1963,1963,0.018556981362664222,61
115534,2240,2240,0.014769673704414588,71

146544,3101,3101,0.014638471460819091,81
180520,3397,3397,0.014889157052036733,91
216254,3573,3573,0.014129176694464656,101

250427,3417,3417,0.014769057443010564,111
285664,3523,3523,0.014240514232199108,121

320086,3442,3442,0.014762826099587473,132
358070,3798,3798,0.013284830454928391,142

395201,3713,3713,0.013596321133284857,152

Le rsultat est retourn sous forme de tableau. La premire valeur indique le nombre de
lignes insres. Par dfaut, cassandra-stress effectuera linsertion dun million de lignes
avant de sarrter. Les deuxime et troisime colonnes indiquent le taux doprations et de
crations de cls, la quatrime colonne indique la latence moyenne des oprations, et la
dernire valeur reprsente le nombre de secondes dexcution de la range doprations.

Tests gnriques
Pour les moteurs NoSQL qui ne possdent pas doutil de test de charge, vous pouvez
crire du code qui attaque le serveur avec des requtes en crant plusieurs threads. Voici
un exemple de code Python, qui utilise le module threading de Python, et qui reprend le
code dimportation de documents XML dans MongoDB du chapitre 14 :
# !/usr/bin/python
# coding=utf-8
import threading

import time
import urllib

import xmltodict
import pymongo
from pymongo import Connection

rss = http://www.franceinfo.fr/rss/tag/1

nombre_de_threads = 20
document = urllib.urlopen(rss)

o = xmltodict.parse(document)

nb_iterations = 20
def insert_mongo(iterations):

cn = Connection(host="localhost", port=27017)
db = cn["france_info"]

count = 0
while count < iterations:
db.actus.drop()

db.actus.save(o, safe=True)
time.sleep(1)
count += 1

# cration de threads
count = 0
while count < nombre_de_threads:

print "cration du thread %s" % count


threading.Thread(None, insert_mongo, None, (nb_iterations,)).start()
count += 1

Ce code nest pas parfait, notamment en ce qui concerne la gestion des threads qui est trop
lmentaire et il sera difficile dinterrompre lexcution de code immdiatement (pour une
meilleure gestion des threads en Python, consultez la page suivante :
http://python.developpez.com/faq/?page=Thread). Il sagit dun code de dmonstration et
lessentiel y est. Nous dclarons une fonction qui va, lintrieur dune boucle, supprimer
la collection actus et la recrer en y insrant un document rcupr du flux RSS de France
Info. Cette opration sera ralise 20 fois par thread, avec une attente de 1 seconde entre
chaque opration. La fonction sera excute en multithread, par 20 threads au total que
nous crons et dmarrons en boucle galement. Il sagit ici dun exemple trs simple de
petit programme de test de charge. Le but est de vous montrer quil sagit dun
dveloppement relativement ais, ce qui devrait vous encourager raliser ce genre de test
trs important pour valuer les capacits de votre systme.

Supervision avec les outils Linux


Linux comporte un certain nombre doutils de supervision qui vous permettront de
surveiller les performances de vos bases NoSQL. Le plus utile est sysstat, une collection
doutils de supervision de performances dvelopps par un Franais nomm Sbastien
Godard (http://sebastien.godard.pagesperso-orange.fr/). sysstat peut tre install sur
Debian et Ubuntu par un paquet des dpts officiels :
sudo apt-get install sysstat

Lorsque le paquet est install, vous avez disposition plusieurs outils qui vous fournissent
des indications sur ltat du systme.

La commande iostat
La commande iostat retourne des statistiques de charge disque, cumules depuis le
dmarrage du systme. Lexemple suivant correspond au rsultat dun appel de la
commande iostat sans quaucun paramtre ne soit mentionn.
Linux 3.0.0-29-generic-pae (ubuntu-server-64-fr) 10/02/2013 _i686_ (1

CPU)
avg-cpu: %user %nice %system %iowait %steal %idle

1,62 0,12 1,02 0,40 0,00 96,86


Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
scd0 0,00 0,00 0,00 48 0

sda 18,31 76,36 82,08 11397422 12252281


dm-0 5,06 38,24 37,50 5708357 5596904
dm-1 20,63 38,07 44,44 5682936 6633612

Les colonnes retournes sont :


Device : le disque physique tel quil apparat dans /dev ;
tps : nombre de transactions par seconde, lectures et critures cumules ;
kB_read/s : nombre de Ko lus par seconde ;
kB_wrtn/s : nombre de Ko crits par seconde ;
kB_read : nombre total de Ko lus ;
kB_wrtn : nombre total de Ko crits.
dm-0
Les disques qui commencent par dm- sont des disques logiques crs par LVM (Logical Volume Manager).

Vous pouvez aussi suivre lactivit disque entre deux appels de iostat en mentionnant un
nombre dexcutions en paramtre. Voici un exemple dappel avec quelques options
intressantes :
iostat -mtx sda -d 2 10

Les options sont les suivantes :


m : affiche les statistiques en Mo et non en Ko ;
t : affiche le temps de chaque excution ;
x : affiche des informations tendues (option disponible depuis la version 2.5 du noyau
Linux) ;
sda : ne rcupre les statistiques que pour ce priphrique ;
-d 2 10 : rcupre les statistiques toutes les deux secondes, dix fois au total.
Les premires lignes de rsultat sont reprsentes sur la figure 15-1.

Figure 15-1
Rsultats de la commande iostat

Les colonnes supplmentaires sont :


avgrq-sz : taille moyenne des requtes en nombre de secteurs du disque ;
avgqu-sz : longueur moyenne de file dattente du disque ;
r_await : temps moyen dattente en millisecondes pour les lectures, incluant lattente dans
la file et lexcution ;
w_await : temps moyen dattente en millisecondes pour les critures, incluant lattente
dans la file et lexcution ;
svctm : temps moyen du service, cette valeur doit tre ignore car elle nest plus correcte ;
%util : pourcentage de temps CPU o des demandes ont t effectues sur le disque.
Avec ces indications, vous possdez tout ce dont vous avez besoin pour mesurer lactivit
de vos disques et la pression que fait peser votre moteur NoSQL un moment donn sur
votre sous-systme disque. Surveillez surtout la file dattente (avgqu-sz) et le pourcentage
dutilisation. Une file dattente suprieure 0 indique que des processus attendent que le
disque se libre. Si cette valeur est constamment au-dessus de zro, songez librer le
disque, en ajoutant de la RAM si les donnes peuvent tre caches, ou en rpartissant les
donnes sur plusieurs disques. Un pourcentage dutilisation approchant les 100 % indique
aussi une saturation.

La commande iftop
Nous avons vu comment surveiller lactivit disque. Un serveur de bases de donnes
transmet ses donnes aux clients travers le rseau, il est donc galement important de
surveiller lactivit des interfaces rseau. Outre les compteurs SNMP traditionnels, vous
pouvez suivre en local lactivit rseau grce quelques outils en ligne de commande.
Nous allons quitter provisoirement les outils sysstat pour installer iftop, qui ralise pour les
interfaces rseau la mme chose que la commande top pour les processus : afficher en
temps rel le trafic le plus important. Nous allons installer iftop sur notre systme Ubuntu :
sudo apt-get install iftop

puis nous lexcutons :


sudo iftop -i eth0

Afin de pouvoir accder au trafic de linterface eth0, il faut que iftop soit excut avec des
privilges administrateur, cest pourquoi nous le lanons avec sudo. Nous avons limit
linterface avec loption -i, ce qui nous permet de cibler seulement linterface publique
travers laquelle passe le trafic des clients. La figure 15-2 donne une ide de laffichage de
la commande.

Figure 15-2
Rsultats de la commande iftop

TX signifie transmission, donc envoi, et RX signifie rception.


Pour quitter laffichage interactif, appuyez sur la touche Q.

La commande pidstat
La commande pidstat retourne des informations sur un processus. Vous pouvez lutiliser
pour surveiller diffrents aspects de votre moteur NoSQL, grce aux options suivantes :
-d : informations sur lactivit disque ;
-r : utilisation mmoire et fautes de pages ;
-s : utilisation de la pile (stack) ;
-u : utilisation du CPU ;
-w : changements de contextes.
De plus, loption -C permet de filtrer les processus par expression rationnelle pour ne
conserver que les processus souhaits. Voyons un premier exemple :
pidstat -C redis-server -d -p ALL

qui retourne lactivit disque pour redis-server depuis le dmarrage du systme. Nous
indiquons -p ALL pour afficher tous les processus, mme ceux pour lesquels aucune
statistique nest afficher. Nous obtenons une ligne avec des statistiques 0 si le
processus na pas encore eu dactivit. Le rsultat est le suivant :
Linux 3.0.0-29-generic-pae (ubuntu-server-64-fr) 10/02/2013 _i686_ (1 CPU)
10:35:23 PID kB_rd/s kB_wr/s kB_ccwr/s Command

10:35:23 32155 1,96 0,10 0,00 redis-server


Ces informations correspondent ce quon peut obtenir avec iostat.
Loption -r donne des informations sur loccupation mmoire et les fautes de pages. Une
faute de page indique un dfaut de mmoire : le processus cherche accder une page de
mmoire dans lespace dadressage virtuel (la RAM rendue disponible par le systme)
laide de ladresse fournie par le systme dexploitation, et cette page nest pas prsente
ladresse dsigne. Il faut donc que le systme la rcupre. Si la faute est majeure (major
page fault), la page nest pas prsente en mmoire, mais sur le disque (en swap), il faut
donc la remonter en mmoire. Un excs de fautes de pages majeures indique
probablement quil ny a pas assez de mmoire dans le systme. Cette indication est par
exemple intressante pour MongoDB, qui sappuie pour son systme de cache sur les
fonctionnalits du systme dexploitation. Voici un exemple dappel :
pidstat -C mongod -r -p ALL

et son rsultat :
Linux 3.0.0-29-generic-pae (ubuntu-server-64-fr) 10/02/2013 _i686_ (1 CPU)
10:44:52 PID minflt/s majflt/s VSZ RSS %MEM Command

10:44:52 13524 0,13 0,01 148928 1520 0,15 mongod

Les colonnes signifient :


minflt/s : nombre de fautes de pages mineures par seconde ;
majflt/s : nombre de fautes de pages majeures par seconde ;
VSZ : taille en mmoire virtuelle (la RAM alloue par le systme au processus) en Ko ;
RSS (Resident Set Size) : taille de mmoire physique, non swappe, utilise par le
processus et exprime en Ko ;
%MEM : pourcentage de mmoire physique utilise par le processus.
La diffrence entre VSZ et RSS indique la partie de la mmoire du processus qui est dans le
swap. Cette occupation mmoire inclut lutilisation de bibliothques partages, qui
peuvent aussi tre utilises par dautres processus. Vous pouvez obtenir des dtails
doccupation mmoire laide de la commande pmap (voir chapitre 14, page 274).

La commande sar
installe un dmon qui collecte des statistiques dutilisation travers le temps. Pour
sysstat
activer cette collecte, ditez le fichier de configuration /etc/default/sysstat et changez
ENABLED="false"

en
ENABLED="true"

Les statistiques seront collectes dans /var/log/sysstat/ et pourront tre interroges avec la
commande sar. Les options de la commande sar sont :
-B : statistiques de pagination ;
-b : statistiques dentres-sorties ;
-d : statistiques disque pour chaque bloc prsent dans /dev ;
-H : statistiques dutilisation des hugepages (voir encadr suivant) ;
-m : statistiques de gestion dnergie ;
-n : statistiques rseau ;
-q : statistiques sur les files dattente et de la charge du systme ;
-R : statistiques mmoire ;
-r : statistiques dutilisation de la mmoire ;
-u : utilisation des CPU ;
-W : statistiques de swap ;
-w : crations de tches et switchs du systme.
Les hugepages
Les hugepages sont des zones de mmoire qui sont alloues via la fonction systme mmap() a des tailles bien plus
importantes que les pages de mmoire traditionnelles. Cette allocation permet de meilleures performances car la
mmoire est accde plus rapidement, sans quil soit ncessaire de recourir des tables de traduction de ladresse
mmoire. Par ailleurs, ces pages sont fixes en mmoire et ne peuvent tre swappes. Les moteurs bass sur Java
peuvent bnficier de ces avantages en configurant loption UseLargePageSize de la JVM.

Voici un exemple dappel de la commande sar :


sar -q 1 3

qui demande des statistiques de file dattente pour un intervalle dune minute, sur les trois
dernires valeurs enregistres. Voici le rsultat :
Linux 3.0.0-29-generic-pae (ubuntu-server-64-fr) 10/02/2013 _i686_ (1 CPU)

17:37:55 runq-sz plist-sz ldavg-1 ldavg-5 ldavg-15 blocked


17:37:56 0 264 0,00 0,02 0,09 0
17:37:57 0 264 0,00 0,02 0,09 0

17:37:58 0 264 0,00 0,02 0,09 0


Moyenne : 0 264 0,00 0,02 0,09 0

Nous voyons quil y avait 264 tches actives (plist-sz). La charge moyenne du systme
pour les cinq dernires minutes (ldavg-5) tait de 0,02, et de 0,09 durant les quinze
dernires minutes. Cela reprsente 2 % et 9 % de charge, 1 correspondant une charge de
100 % du processeur.

Supervision avec les outils intgrs


Les moteurs comportent souvent leurs propres outils de monitoring, qui vous permettent
de suivre lactivit en rcuprant des compteurs internes spcifiques. Voici quelques
exemples sur nos moteurs.

MongoDB
MongoDB inclut la commande mongostat, qui retourne en permanence le nombre de
requtes excutes et dautres indicateurs. Il suffit dexcuter la commande mongostat dans
un shell. La figure 15-3 donne un exemple de quelques lignes de rsultats.
Figure 15-3
Rsultats obtenus avec la commande mongostat

Les indicateurs sont les suivants :


insert : nombre dobjets insrs par seconde ;
query : nombre de requtes par seconde ;
update : nombre dobjets modifis par seconde ;
delete : nombre dobjets supprims par seconde ;
getmore : nombre dappels de curseurs sur des objets ouverts, par seconde ;
command : nombre de commandes par seconde ;
flushes : nombre de fsync() par seconde, donc de flush de la mmoire vers le disque ;
mapped : total des donnes mappes en mmoire, en Mo ;
vsize : taille de la mmoire utilise par MongoDB ;
res : taille de la mmoire rsidente, non swappe ;
faults : nombre de fautes de pages par seconde (voir la section prcdente sur la
commande pidstat, page 296) ;
locked % : pourcentage de temps utilis o un verrou global dcriture est pos ;
idx miss % : pourcentage de tentatives daccs une page dindex qui a dclench une
faute, donc o la page dindex ntait pas en mmoire et a d tre charge depuis le
disque ;
qr|qw : longueur des files dattente de lecture (r) et dcriture (w) ;
ar|aw : nombre de clients en train de lire (r) et dcrire (w) ;
NetIn : trafic rseau entrant en octets ;
NetOut : trafic rseau sortant en octets ;
conn : nombre de connexions ouvertes.

Cassandra
Cassandra inclut loutil nodetool, qui permet dadministrer certains de ses lments et de
rcuprer des informations. Les commandes suivantes sont utiles pour la supervision :
nodetool ring : retourne des informations sur lanneau des nuds ;
nodetool info : retourne des informations sur le nud sur lequel il est excut ;
nodetool cfstats : retourne des statistiques sur les familles de colonnes ;
nodetool tpstats : retourne des informations sur les threads ;
nodetool netstats : retourne des informations sur lactivit rseau ;
nodetool compactionstats : retourne des informations sur les oprations de compactage.
Voici un exemple dappel de nodetool info :
Token : 50296331533206892393222798876815311727

Gossip active : true


Thrift active : true

Load : 316.99 MB
Generation No : 1360329584
Uptime (seconds) : 190262

Heap Memory (MB) : 346,26 / 478,00


Data Center : datacenter1
Rack : rack1

Exceptions : 0
Key Cache : size 480 (bytes), capacity 24117216 (bytes), 13 hits, 23 requests,
0,565 recent hit rate, 14400 save period in seconds

Row Cache : size 0 (bytes), capacity 0 (bytes), 0 hits, 0 requests, NaN recent
hit rate, 0 save period in seconds

Nous obtenons ltat du nud, la taille occupe en mmoire, la taille et les statistiques du
cache des cls et du cache des lignes. En combinant les diffrentes commandes nodetool,
vous pourrez effectivement surveiller lactivit de vos nuds Cassandra.

Redis
Redis comporte la commande monitor qui permet de suivre son activit en temps rel, sous
forme de trace de requtes. Nous pouvons la lancer avec redis-cli, de la manire suivante :
redis-cli monitor

Voici un extrait du rsultat :


1360534695.969207 [0 127.0.0.1:48804] "SET" "300730417307320320" "@Adrienbrt @flobrager
@florianelcrt je redis bref !"

1360534697.503696 [0 127.0.0.1:48895] "INFO"

1360534717.449005 [0 127.0.0.1:48902] "INFO"


1360534735.673057 [0 127.0.0.1:48804] "SET" "300730583879938049" "Ej jutro musze isc

na 5 godzin do sql, jechac do ortodonty, do kosmetyczki i na korki z chemii. \xc5\

xbbal dupe sciska nie?"


1360534737.458720 [0 127.0.0.1:48914] "INFO"

1360534743.703835 [0 127.0.0.1:48804] "SET" "300730617501458432" "Startups that have


chosen sql how do you keep your site online nonstop when performing updates?: I

dont know http://t.co/EvxUIwQ2"


1360534752.678744 [0 127.0.0.1:48804] "SET" "300730655095001088" "Personne me respecte

ici jvous ldis , elle mle redit."


1360534757.535845 [0 127.0.0.1:48922] "INFO"
1360534777.461079 [0 127.0.0.1:48929] "INFO"

1360534792.001277 [0 127.0.0.1:48804] "SET" "300730820111499264" "SQL 2008 Forum - SQL

Server Command line utility for windows XP: Hello, I am trying to run a job lying on a
SQL S http://t.co/g2DX1q4W"

1360534795.141437 [0 127.0.0.1:48804] "SET" "300730833348751361" "RT @Mehdi_Carter:

Personne me respecte ici jvous ldis , elle mle redit."

Comme vous pouvez le constater, chaque commande reue par Redis est montre telle
quelle. La premire partie du rsultat correspond au timestamp de la machine.
Performances de monitor
Lexcution de la commande monitor peut diminuer les performances de Redis de 50 %. En guise dexemple,
consultez le test reproduit sur la page daide de la commande monitor ladresse suivante :
http://redis.io/commands/monitor.

Nous avons galement vu au chapitre 10 que Redis inclut un slowlog, qui conserve une
trace des requtes estampilles lentes.

Supervision avec Ganglia


Ganglia (http://ganglia.sourceforge.net/) est un systme de supervision qui se distingue de
ses concurrents libres comme Nagios par ses capacits de monte en charge. Conu ds le
dpart pour assurer la supervision darchitectures fortement distribues (en grid), il permet
de surveiller des dizaines de milliers de machines. Dvelopp luniversit de Berkeley, il
est utilis par un grand nombre dentreprises de taille importante qui doivent grer un trs
grand parc de machines, comme Twitter, Flickr, Reuters, Boeing et mme Microsoft.
Comme son nom lindique ( ganglia est le pluriel de ganglion, le tissu interconnect du
systme nerveux), Ganglia est distribu et dcentralis. Son architecture ressemble
conceptuellement aux systmes dcentraliss comme Dynamo ou Cassandra. Afin de
pouvoir monter en charge sans problme, chaque machine sur laquelle Ganglia est install
interroge elle-mme les donnes locales. Elle les envoie ensuite des collecteurs de
statistiques, potentiellement redondants, dans un cluster de machines travers une adresse
multicast par dfaut. chaque niveau du fonctionnement de Ganglia, les performances
ont t soignes pour que cette activit ne charge pas de faon significative les nuds et le
rseau. La communication se fait via UDP travers une adresse multicast. Ganglia
comporte nativement toutes les mtriques ncessaires pour surveiller le systme et le
rseau, ainsi quun environnement Hadoop, HDFS et Hbase laide de sa capacit
rcuprer des mtriques JMX.
JMX
JMX (Java Management Extensions) est une API pour Java permettant de grer le fonctionnement dune
application Java en cours dexcution. JMX est intgr dans J2SE depuis la version 5.0. Attention, JMX est
dsactiv par dfaut dans la version 5.0. Utilisez java -Dcom.sun.management.jmxremote.
Des modules de statistiques peuvent tre dvelopps en Python ou C et tre ajouts
Ganglia.
Ganglia est compos de plusieurs modules qui assurent diffrentes tches permettant la
distribution du travail de rcupration des compteurs. Le dmon gmond recueille les
mesures. Le dmon gmetad recueille les statistiques. Une application web (dmon gweb)
permet dafficher ces statistiques et daccumuler des graphes laide de RRDTool, une
bibliothque de stockage et daffichage de donnes journalises dans le temps.

Installer Ganglia
Sur Ubuntu, la faon la plus simple dinstaller Ganglia consiste utiliser le paquet de la
distribution officielle :
sudo apt-get install ganglia-monitor

qui installe gmond, le dmon de supervision, dont vous aurez besoin sur la plupart des
nuds.
Bogue du paquet ganglia-monitor
Ce paquet peut boguer sur votre distribution et afficher une erreur pendant la phase de configuration de dpkg (le
gestionnaire de paquets) : useradd: group ganglia exists - if you want to add this user to that group,
use -g. Si vous rencontrez cette erreur, lancez la commande suivante pour ajouter le compte ganglia dans le
groupe : sudo useradd ganglia -g ganglia. Relancez ensuite linstallation du paquet.

Le dmon est automatiquement dmarr par linstallation. Le fichier de configuration se


trouve pour nous dans /etc/ganglia/gmond.conf. Nous allons changer le nom du cluster, qui est
unspecified par dfaut.
Nous installons ensuite linterface web sur notre machine. Dans une installation en cluster,
vous installerez bien sr ce paquet sur une seule machine, celle sur laquelle vous vous
connecterez pour visualiser vos rapports.
sudo apt-get install ganglia-webfrontend

Ensuite, nous devons ajouter le fichier de paramtrage la configuration dApache. Ce


fichier, situ dans le rpertoire /etc/ganglia-webfrontend/apache.conf, contient une seule ligne,
qui cre lalias vers le rpertoire o lapplication web est installe. Nous crons un lien
symbolique vers ce fichier dans la configuration dApache et nous redmarrons Apache
pour que cette modification soit prise en compte :
sudo ln -s /etc/ganglia-webfrontend/apache.conf /etc/apache2/sites-enabled/ganglia.conf

sudo apache2ctl restart

Nous vrifions ensuite ladresse http://serveur/ganglia en la saisissant dans la barre


dadresses de notre navigateur web.
Voyons maintenant comment ajouter des compteurs spcifiques nos moteurs NoSQL.

Ajouter des modules Python


Depuis sa version 3.1, Ganglia permet de crer des modules de rcupration de compteurs
externes et des modules Python. Un certain nombre de modules pour des outils comme
MongoDB, Redis, CouchDB et ElasticSearch sont disponibles sur GitHub ladresse
suivante : https://github.com/ganglia/gmond_python_modules/t.
Nous devons modifier le fichier de configuration /etc/ganglia/gmond.conf pour ajouter la
bibliothque qui gre les modules Python. Nous ajoutons la section suivante dans la
section modules :
modules {

module {

name = "python_module"
path = "/usr/lib/ganglia/modpython.so"

params = "/usr/lib/ganglia/python_modules/"

}
}

contient aussi la ligne suivante :


gmond.conf

include (/etc/ganglia/conf.d/*.conf)

Cest donc cet endroit que nous allons dposer les fichiers .conf de ces modules. Certains
fichiers de configuration Python ont lextension .pyconf, nous ajoutons donc cette ligne
dans gmond.conf :
include (/etc/ganglia/conf.d/*.pyconf)

Nous rcuprons ensuite les modules grce git :


git clone git://github.com/ganglia/gmond_python_modules.git

puis nous crons les rpertoires et nous copions les fichiers :


sudo mkdir /etc/ganglia/conf.d/
sudo mkdir /usr/lib/ganglia/python_modules/
cd gmond_python_modules/

sudo cp mongodb/conf.d/mongodb.conf /etc/ganglia/conf.d/


sudo cp mongodb/python_modules/mongodb.py /usr/lib/ganglia/python_modules/

sudo cp redis-gmond/conf.d/redis-gmond.pyconf /etc/ganglia/conf.d/


sudo cp redis-gmond/python_modules/redis-gmond.py /usr/lib/ganglia/python_modules/

sudo cp couchdb/conf.d/couchdb.pyconf /etc/ganglia/conf.d/

sudo cp couchdb/python_modules/couchdb.py /usr/lib/ganglia/python_modules/

Nous redmarrons ensuite gmond :


sudo service ganglia-monitor restart

Aprs quelque temps, nos compteurs apparaissent sur linterface web de Ganglia,
ladresse http://serveur/ganglia. Un exemple est reproduit sur la figure 15-4.
Figure 15-4
Interface web de Ganglia
16
tude de cas : le NoSQL chez Skyrock

Afin dillustrer lutilisation des moteurs NoSQL, nous avons choisi de prendre pour
exemple la chane de radio Skyrock, bien prsente sur le Web, notamment travers les
Skyblogs. Pour ses diffrents besoins Internet, Skyrock a recours des moteurs NoSQL
depuis quelques annes.
Avant mme davoir opt pour des solutions officiellement NoSQL, les dveloppeurs
de Skyrock, dont la politique a toujours t de faire appel des outils libres, utilisaient le
classique tandem PHP-MySQL dans une architecture LAMP (Linux, Apache, MySQL,
PHP). Cette architecture constitue toujours la base du stockage des donnes du site
skyrock.com, qui compte ce jour environ 200 serveurs MySQL et memcached. Mais
mme lorsque les dveloppeurs de Skyrock ne faisaient appel qu MySQL, il sagissait
dune utilisation plutt non relationnelle du moteur, en vitant les jointures et en stockant
lquivalent de paires cl-valeur dans les tables MySQL. Tous les accs aux donnes
contenues dans chaque table seffectuent par lintermdiaire de la cl, dfinie comme cl
primaire de la table, sans utilisation de recherche sur dautres colonnes par indexation
secondaire. Pour assurer la monte en charge, les dveloppeurs de Skyrock ont commenc
casser le relationnel encore plus, en sparant tout dabord les bases de donnes par
service (une base pour les blogs, une base pour les articles, une base pour les
commentaires, etc.), ce qui leur a permis dutiliser des serveurs diffrents pour chaque
lment. Cela veut dire bien sr que les jointures ont disparu de leur code SQL, et quelles
ont d tre ralises du ct du client. Pour assurer ensuite de nouvelles montes en charge
horizontales, ils ont partitionn (shard) partir de 2007 les donnes de chaque service sur
dix machines, sur des plages de cls, en utilisant la technique classique du modulo.
lpoque, lide du hachage consistant ntait pas trs rpandue, et comme ils ne
comptaient pas ajouter trs rgulirement de nouvelles machines, cela na pas pos de
problme en pratique.
Mais, vous direz-vous, comment effectuer des recherches ? Par exemple, si les articles de
blog sont retrouvs par la cl (comme un identifiant darticle), comment faire pour
rechercher les articles par mot-cl, par sujet ou par date de publication ? Tout dabord,
notons que certaines recherches ne sont pas pertinentes sur le site skyrock.com, telles que
le regroupement darticles de blog par mois, comme cela est souvent propos sur les
plates-formes de publication de blogs. Pour le reste, les performances sont assures par le
cache en mmoire et la cration de listes inverses. Par exemple, pour distinguer les
articles publis des brouillons, la liste des articles dun utilisateur est rcupre par sa cl
et stocke dans le cache de memcached. Le filtre quivalent de la clause WHERE dans une
requte SQL est effectu par une boucle de recherche dans le code client, et reste rapide
grce au stockage en cache. Cette approche implique une dnormalisation et donc une
duplication des donnes, ce qui augmente la taille du cache, mais cette solution est tout
fait satisfaisante pour Skyrock.

Le dveloppement de solutions en interne


La question du maintien de la session utilisateur stait aussi pose. Habituellement, une
session sur un site web fait appel la fois au client et au serveur : du ct de lutilisateur,
un cookie maintient un UUID de session gnr par PHP, et du ct du serveur, cet UUID
est maintenu, par exemple en base de donnes. Pour permettre au traitement serveur dtre
plus rapide, Frank Denis ( qui lon doit notamment le serveur FTP libre PureFTPD) a
dvelopp en 2004 un outil de maintien de sessions du ct serveur pour Skyrock nomm
Sharedance. Le projet est libre et peut tre tlcharg ladresse suivante :
http://www.pureftpd.org/project/sharedance.
Sharedance est constitu dun dmon crit en C qui coute sur un port TCP les requtes de
clients qui lui envoient des demandes dcriture et de lecture de paires cl-valeur, et qui
les maintient sur un systme de fichiers, quivalent simplifi de memcached (Sharedance a
t publi pour la premire fois en 2004, memcached en 2003). Afin dassurer la partie
cache, il suffit de faire crire Sharedance sur un ramdisk tel que tmpfs sur Linux.
Le ramdisk
Le ramdisk est une partition visible par le systme de fichier et qui est en ralit une zone de la mmoire vive. Cest
donc la simulation dun disque en RAM, pour offrir de grandes performances daccs des fichiers.

Le maintien en RAM est ainsi assur moindre frais. Les oprations dcriture et de
lecture des paires sont trs simples. Le code source de Sharedance implmente le
minimum ncessaire pour permettre du code PHP de travailler avec lui :
sharedance_store($key, $data)

sharedance_fetch($key)
sharedance_delete($key)

en dautres termes, de simples GET et SET.

Topy
En 2008, un autre besoin sest fait sentir : tablir et afficher des classements dutilisateurs
en fonction de diffrents critres : nombre de visites, ge, sexe, etc. Ces listes ont dabord
t gnres en base de donnes, dans des tables de rsultats, par des requtes planifies.
Mais pour assurer des calculs statistiques plus rapides, Nicolas Vion, lun des
dveloppeurs de Skyrock, a cr un outil nomm Topy. Le code source en C++ de Topy et
son extension PHP sont disponibles ladresse suivante : https://github.com/zmoo/topy.
Topy est un serveur qui rpond en TCP ou en UDP, et dont la tche consiste gnrer des
statistiques et des classements en temps rel. Pour ce faire, il manipule des paires cl-
valeur, la cl tant, par exemple, une cl dutilisateur ou tout type de valeur sur laquelle
des classements doivent tre effectus, et la valeur est une structure qui contient des
agrgats sur lesquels des oprations simples peuvent tre ralises, comme un add. Sur
skyrock.com, Topy est utilis pour tous types de classements (visites, votes, tags, kif ,
thmes, etc.) et galement pour des statistiques internes. La figure 16-1 montre un
fragment de page de profil utilisateur o Topy est mis en uvre.

Figure 16-1
Page de profil Skyrock qui utilise Topy

Loutil a volu avec le temps pour intgrer de nouveaux types de cls, par exemple pour
les classements de vidos. Lextension Topy pour PHP implmente aussi une gestion de
pool de connexions persistantes et une dsrialisation du flux entre le serveur et le client
PHP, en format PHP serialize. Le but est doptimiser les performances tous les niveaux
de la chane.

Fluxy
En 2009, afin de grer les listes darticles des skyblogs, Nicolas Vion a dvelopp un autre
outil, Fluxy, disponible cette adresse : http://fluxy.tuxfamily.org/. Comme il est indiqu
sur la page de Fluxy, loutil est toujours en production chez Skyrock et permet de grer
des listes darticles de plusieurs dizaines de millions dutilisateurs sur deux machines, une
active et une passive pour la redondance. Fluxy maintient en mmoire des listes darticles
par cl dutilisateur. Les listes sont finies et utilisent un algorithme FIFO (First In, First
Out : premier entr, premier sorti) pour conserver un nombre maximal darticles. Les
articles sont conservs par ordre chronologique, avec un certain nombre de champs dans la
structure : date, type, tags et corps de larticle notamment. Fluxy gre donc une liste
darticles. Le besoin de Skyrock tant dafficher une liste darticles publis par les
contacts ou amis dun utilisateur, il faut agrger ensuite ces listes pour afficher les
dernires publications damis. Cest Fluxy qui soccupe de cette opration, en rcuprant
une liste damis par la cl de lutilisateur, puis en en btissant une liste pondre darticles
rdigs par ces amis. La liste est simple et ne contient pas le texte ou les ressources de
larticle. Chaque appel sur un lment de cette liste (par exemple, lutilisateur voulant
accder un de ces articles) fera lobjet dun appel la ressource contenue dans MySQL
et cache dans memcached.
La liste damis elle-mme est stocke dans MySQL mais de faon non relationnelle. Si
vous maintenez une relation entre des utilisateurs dans une base de donnes relationnelle,
votre rflexe est de crer une table de correspondance entre deux identifiants
dutilisateurs. Cest bien entendu ce qua fait Skyrock. Si lamiti est bidirectionnelle,
cest--dire quen tant ami avec quelquun, cette autre personne est automatiquement
amie avec vous, vous penserez crer simplement un index secondaire sur la colonne
identifiant lami, comme illustr sur la figure 16-2.
Figure 16-2
La table damitis

Il sagit de lapproche relationnelle traditionnelle. Mais ce mcanisme prsente un


inconvnient : si vous comptez sharder votre table sur la cl de lutilisateur, les recherches
par lindex secondaire seront impossibles ou devront tre effectues sur tous les shards, ce
qui est impraticable. Cest pour cette raison que les dveloppeurs de Skyrock ont dcid
de maintenir une liste duplique damis, comme illustre sur la figure 16-3.

Figure 16-3
La capacit de sharder la table damitis

Toutes les recherches se font donc sur la cl primaire, on retrouve effectivement une pure
approche cl-valeur.

Lutilisation de Redis
MySQL reste la solution de stockage long terme la plus utilise chez Skyrock. En ce qui
concerne lacclration des accs et la manipulation de donnes plus volatiles, Redis a t
choisi pour plusieurs dveloppements rcents. Redis est vraiment intressant pour
sassurer des latences les plus faibles en accs et manipulation de donnes. En 2010, les
dveloppeurs de Skyrock ont travaill sur la manire la plus efficace possible dafficher
les utilisateurs en ligne sur skyrock.com (figure 16-4).

Figure 16-4
Un fragment du site Skyrock utilisant Redis

Comment grer une liste aussi dynamique ? Les dveloppeurs sont dabord partis sur une
approche MySQL et memcached, qui a fonctionn pendant quelques temps. Afin dobtenir
de meilleures performances et de sassurer de pouvoir tenir la charge dans le futur, ils ont
dvelopp en parallle une solution utilisant Redis. Le principe est simple : la liste des
utilisateurs en ligne est rafrachie en temps rel et partitionne toutes les minutes. Cela
permet donc de maintenir dans Redis une cl qui correspond une minute. Dans la valeur,
un ensemble (set) Redis est maintenu avec la liste des identifiants dutilisateurs en ligne.
Si vous vous connectez sur skyrock.com et que vous souhaitez afficher la liste de vos amis
en ligne, le code cre une cl temporaire sur votre identifiant, incluant un set de votre liste
damis. Il suffit ensuite de faire une intersection des deux sets pour retrouver vos amis en
ligne. Voici en quelques lignes de code, que nous saisissons dans linvite interactive de
Redis (redis-cli), le principe de la recherche :
SELECT 1
SADD 20121012T12:53 10 24 76 934 512 534 954 123 404 65

SMEMBERS 20121012T12:53

SADD 734 523 76 834 634 123 811 450 512

SINTER 734 20121012T12:53


PEXPIRE 734 1

La premire ligne slectionne une base de donnes autre que celle par dfaut (0) pour
isoler le travail. Ensuite, nous utilisons la commande SADD pour ajouter un set avec la cl
20121012T12:53, cest--dire un datetime la granularit de la minute, en loccurrence 12:53
le 12 octobre 2012. Nous ajoutons dix identifiants, nous aurions pu en ajouter 14 000.
Nous allons essayer cela dans un instant, mais pour le moment, faisons notre essai avec
ceci. Admettons que lutilisateur 734 se connecte et que nous voulons afficher sa liste
damis. Nous crons un set temporaire sur la cl 734 contenant les identifiants des amis,
ici au nombre de huit. Il nous suffit ensuite de faire un SINTER sur les deux cls pour
retourner lintersection des deux sets, donc la liste damis en ligne. Finalement, nous
affectons une priode dexpiration de notre cl temporaire dune milliseconde. Redis
nettoiera la cl 734 pour nous. Les rsultats de lintersection sont illustrs sur la figure 16-
5.

Figure 16-5
Rsultat du calcul dintersection dans Redis
Tester la charge
Essayons de voir comment se comporte cette solution avec une charge plus raliste. Nous
allons produire une cl comportant 14 000 identifiants dutilisateurs, que nous allons
galement alourdir en crant des UUID. Avant cela, nous allons vider notre base de
donnes 1 pour repartir zro :
SELECT 1

FLUSHDB

Ensuite, nous crivons le code Python suivant :


import uuid

import redis

from datetime import datetime, time

r = redis.StrictRedis(host=localhost, port=6379, db=1)


cle = datetime.now().strftime(%Y-%m-%dT%H:%M)
user = uuid.uuid4()

pipe = r.pipeline(transaction=False)
pipe.sadd(cle, user)
for i in range(14000):

id = uuid.uuid4()
if i % 100 == 0:
pipe.sadd(user, id)

pipe.sadd(cle, id)
pipe.execute()

Nous utilisons ici le module redis-py pour accder Redis. Nous ouvrons une connexion
sur la machine locale en indiquant la base de donnes 1. Nous dfinissons la cl
correspondant la minute actuelle et nous crons un premier utilisateur grce au module
uuid de Python. Il nous servira dutilisateur tmoin. Afin dviter les allers-retours vers
Redis, nous utilisons un objet pipeline qui va permettre de transmettre les requtes vers
Redis par lots. Nous insrons 14 000 UUID dans la cl correspondant la minute
courante, et en utilisant un modulo 100, nous crons 140 amis dans la cl temporaire de
notre utilisateur tmoin. Afin de mesurer les performances de lopration, nous utilisons la
classe de profilage cProfile de Python, en appelant notre script (que nous avons nomm
skyrock.py) ainsi :

python -m cProfile -o skyrock.profile skyrock.py

Environnement Python
Pour une fois, nous navons pas excut ce script dans notre environnement Python (~/python_env/nosql/) car un
bogue actuel rend indisponible le module urandom dans lenvironnement, ncessaire pour utiliser le module uuid.

Les informations de performances seront stockes dans le fichier skyrock.profile que nous
analyserons ensuite. Voyons dabord laide du client Redis si tout sest bien pass :
SELECT 1

KEYS *

Nous obtenons le rsultat suivant :


1) 2012-10-12T15:28
2) 59ddefc6-9799-4ae1-94c5-11d8711eea7b

Nous avons bien nos deux cls. Vrifions le nombre dlments laide de linstruction
SCARD qui retourne le nombre dlments dun set :

SCARD 2012-10-12T15:28
SCARD 59ddefc6-9799-4ae1-94c5-11d8711eea7b

Nous obtenons bien 14 001 et 140 membres, respectivement. Il nous reste raliser
lintersection :
SINTER 59ddefc6-9799-4ae1-94c5-11d8711eea7b 2012-10-12T15:28

Le rsultat est instantan et retourne les 140 UUID, comme nous le voyons sur la figure
16-6.

Figure 16-6
Rsultat de lintersection sur un ensemble de 14 000 membres

Voyons enfin loccupation en mmoire laide la commande INFO qui retourne pour notre
exemple :
# Memory

used_memory:1639192

used_memory_human:1.56M

ce qui est trs raisonnable. Voyons enfin les performances indiques par Python. Nous
ouvrons le fichier de profil laide du module pstats de Python :
python -m pstats skyrock.profile

ce qui nous ouvre une invite danalyse du fichier de profil. Nous affichons les temps
dexcution les plus hauts :
strip
sort time

stats 30

Ces commandes de pstats provoquent un affichage des trente oprations les plus coteuses
en termes de temps dexcution du script. Le rsultat est illustr sur la figure 16-7.
Figure 16-7
Analyse de temps dexcution avec pstats

Nous voyons que le script skyrock.py sest excut en 1,34 secondes, que la gnration des
UUID a demand environ une demi-seconde et lexcution du pipeline, 650 millisecondes.
Plutt pas mal pour linsertion de 14 141 UUID en tout dans Redis avec un langage client
interprt. Bien sr, nous sommes en local, donc le rseau nentre pas en ligne de compte.
Ce petit exercice nous permet de dmontrer la simplicit et lefficacit de lutilisation de
Redis pour ce genre de besoins. En ralit, Skyrock utilise une mthode juste un peu plus
complique, mais vous voyez que la rapidit de Redis le permet. En effet, les cls
maintenues par minute dans Redis accumulent les utilisateurs qui ont envoy une requte
durant cette minute. Sur un site web, il est bien sr impossible (sans passer par de lAjax,
par exemple) de savoir si le navigateur de lutilisateur est toujours ouvert sur une page,
donc sil est toujours connect. Pour savoir si un ami est en ligne, le code de Skyrock
utilise cette rgle : si on trouve un identifiant dami dans les cinq dernires minutes, cela
veut dire quil est en ligne. En Redis, cela veut dire quil faut effectuer une union des sets
des cinq dernires cls, laide de linstruction SUNION, puis faire lintersection avec le
rsultat. Dans les dernires versions de Redis, cela pourrait tre ralis du ct du serveur
avec un script en langage Lua.

Contourner les problmes


En 2010, en mettant cette solution en place avec Redis, les dveloppeurs de Skyrock se
sont heurts un problme inhrent au client PHP : comme il ny avait pas encore de
support du pipelining comme nous lavons utilis dans notre script en Python, la cration
du set temporaire incluant la liste damis se rvlait peu performante, uniquement cause
du client PHP. Leur solution a t de dvelopper lenvoi en Redis en utilisant les fonctions
daccs direct au rseau de PHP, en crant des sockets avec fsockopen() et en envoyant ainsi
les requtes au serveur Redis, ce qui a permis de profiter de toutes les fonctionnalits de
Redis. En dautres termes, pour pallier les limitations du driver PHP, ils ont dvelopp le
leur afin dintgrer les fonctionnalits de pipelining et de pouvoir ajouter plusieurs
membres un ensemble en une seule commande (la commande SADD permet dajouter
plusieurs lments un ensemble depuis Redis 2.4). Comme pour les outils Topy et Fluxy,
Skyrock est log la mme enseigne que beaucoup de socits du web qui utilisent le
NoSQL : ces technologies sont jeunes et tout ny est pas encore parfait. En revanche, elles
sont libres, ouvertes et souples, il ne reste donc plus qu dvelopper des outils ou des
amliorations pour adapter les moteurs NoSQL aux besoins. Un exemple de cette
dmarche est le contournement de labsence dindex secondaires. Dans plusieurs moteurs
NoSQL, nous lavons vu, laccs se fait exclusivement, ou en tout cas de prfrence, par la
cl. La recherche lintrieur de la structure de la valeur est souvent pnalisante, voire
impraticable. Pour pallier ce type de contrainte, beaucoup dutilisateurs de moteurs
NoSQL dupliquent les donnes ou crent dautres ensembles de paires cl-valeur o la
nouvelle cl est un lment extrait dune valeur des informations dorigine, sur laquelle on
souhaite chercher, et la nouvelle valeur est lidentifiant par lequel on va pouvoir retrouver
toute la structure dans la collection dorigine, cest--dire sa cl.

Utiliser Redis pour le traitement dimages


Redis est un moteur convaincant. Lorsquon la essay et quon a pu constater sa rapidit,
sa simplicit et sa puissance, on commence lui trouver de nombreuses utilisations. Redis
a t mis en place chez Skyrock pour un autre besoin encore que ceux voqus
prcdemment : le traitement des images dposes par les utilisateurs, avec un module
nomm WIR (Web Image Reworker). Lorsquun utilisateur dpose une image sur le site
skyrock.com, il peut la redimensionner et procder un certain nombre de
transformations, par exemple lui appliquer un filtre. Les images originales sont dposes
sur un cluster de stockage. Afin dacclrer le traitement et dviter de saturer les I/O sur
le cluster de stockage, les images sont maintenues en mmoire quelques temps sur les
machines de traitement dans une base Redis, qui stocke les mtadonnes des images et le
fichier lui-mme dans son tat original. Comme il sagit dun groupe de machines de
traitement, les images sont rparties sur les machines en utilisant un algorithme de
consistent hashing sur lURI du fichier. Lorsque le site doit afficher une image, il
reconnat sur quelle machine de traitement doit se trouver limage en recrant le hachage
partir de lURI du fichier. Il fait donc une demande la machine de traitement, qui sert
limage depuis la base Redis si elle y est prsente, ou qui la rcupre depuis le cluster de
stockage et linsre dans Redis si elle ny est pas encore. Rptons que cest toujours
limage originale qui est stocke dans Redis. Le traitement est effectu dynamiquement en
local sur la machine de traitement par rapport la dfinition du traitement choisie par
lutilisateur pour cette image, et renvoye au serveur post-traitement, bas sur nginx qui va
conserver dans un cache disque limage transforme.
Les applications mobiles : Smax
Skyrock est galement prsent sur les smartphones, avec un site optimis pour les
terminaux mobiles (skyrock.mobi) et des applications disponibles pour IOS et Android.
Outre lapplication Skyrock pour couter la radio, une application de chat est disponible,
nomme Smax.
Smax permet de chatter, denvoyer des messages une liste damis et de contacter
dautres utilisateurs de Smax situs proximit, grce son support de la golocalisation.
Smax est dvelopp en Node.JS et utilise MongoDB comme moteur principal de stockage.
Cest un choix naturel pour une application golocalise grce son support des donnes
gospatiales. MongoDB implmente en effet une indexation gospatiale deux
dimensions qui permet deffectuer des recherches sur des documents contenant des
coordonnes de type X et Y ou longitude et latitude.

Exemple de requtes gographiques dans MongoDB


Illustrons travers un exemple lutilisation de MongoDB comme moteur SIG (Systme
dinformation gographique) simplifi (puisquil stocke pour linstant uniquement des
points, pas des polygones). Dans linvite interactive de MongoDB, nous crons les
documents suivants dans une collection que nous nommerons monuments :
db.monuments.save({ _id: eiffel, loc: {lon:2.29510, lat:48.857910}, nom:
Tour Eiffel});

db.monuments.save({ _id: liberty, loc: {lon:-74.0447, lat:40.6894}, nom:


Statue de la Libert});

Nous incluons dans notre document un objet nomm loc, compos de deux coordonnes.
Nous crons ensuite un index gographique sur cet objet :
db.monuments.ensureIndex({loc: 2d});

Nous allons maintenant essayer les oprateurs de recherches gographiques de


MongoDB :
db.monuments.find({ loc: { $nearSphere: [2,48] }});

db.monuments.find({ loc: { $nearSphere: [-74,48] }});

Nous utilisons ici loprateur $nearSphere pour retourner une liste de documents ordonne
par leur proximit avec les coordonnes fournies. Loprateur $near existe galement, mais
il effectue la comparaison par rapport un systme de rfrences plat. $nearSphere effectue
le calcul en se basant sur une gomtrie sphrique. Les rsultats obtenus sont illustrs sur
la figure 16-8.

Figure 16-8
Requtes gographiques dans MongoDB

Nous voyons que les documents sont retourns dans des ordres diffrents, en restituant en
premier les points les plus proches de la coordonne fournie. Pour trouver la distance de
nos coordonnes avec un emplacement, nous pouvons utiliser la commande geoNear :
db.runCommand( { geoNear: monuments, near: [2, 48], spherical: true, num: 1,

distanceMultiplier: 6378000 });

qui retourne un document JSON indiquant la distance du document le plus proche des
coordonnes fournies. Un seul document est retourn car nous avons demand un seul
rsultat (num: 1). Le document retourn est le suivant :
{

ns : test.monuments,
near : 1100010000000110001011001010010000000110001011001010,

results : [
{
dis : 97955.81154374767,

obj : {
_id : eiffel,
loc : {

lon : 2.2951,
lat : 48.85791
},

nom : Tour Eiffel


}
}

],
stats : {
time : 1,

btreelocs : 0,

nscanned : 2,
objectsLoaded : 2,

avgDistance : 97955.81154374767,

maxDistance : 0.015358595804450191
},

ok : 1

Voil pour ce qui concerne lutilisation des outils NoSQL chez Skyrock.
Conclusion : comment se prsente le
futur ?

Au dbut des annes 1980, les systmes de gestion de bases de donnes relationnelles
(SGBDR) furent une technologie de rupture. Ce terme, technologie de rupture est un
concept introduit par Clayton M. Christensen, professeur de business luniversit
Harvard, dans son livre The Innovators Dilemma. Lide du professeur Christensen est
que, principalement dans les innovations techniques, il arrive quune technologie tablie
soit remplace par une technologie naissante qui volue une trs grande vitesse et qui
prend la technologie tablie par surprise. Linnovation peut tre infrieure
technologiquement au modle tabli, mais plus simple et plus accessible. Au fur et
mesure de son dveloppement, elle comble son retard technologique et finit par remplacer
lancienne technologie qui na pas su sadapter. Inversement, linnovation peut tre
suprieure, mais incomprise du grand public car trop innovante justement. Certaines
socits peuvent sen emparer, travailler son dveloppement sans grand cho au dbut, et
finalement surpasser la technologie existante au point de la tuer. Le modle relationnel fut
lpoque un exemple dinnovation de rupture suprieure.
Le mouvement NoSQL est-il une technologie de rupture, qui prend le modle traditionnel
du SGBDR par surprise ? Cest en tout cas ce que disent en filigrane beaucoup de ceux qui
crent ou utilisent des bases NoSQL. Et sil sagit dune technologie de rupture, est-ce une
rupture infrieure ou suprieure ? Dans ce livre, nous avons parl technique car cest
souvent ce qui intresse en premier lieu les informaticiens , mais nous avons aussi essay
dlargir le dbat et daborder des conceptions plus thoriques. En effet, nous pensons que
linformatique a le droit aux concepts et la rflexion. Les approches sont parfois trop
pragmatiques, sans aucune recherche ou intrt sur la raison pour laquelle les choses sont
faites ainsi. Le risque ici est que le modle relationnel ou les diffrents modles NoSQL
soient utiliss sans rflexion, et pour les seconds, uniquement pour suivre le mouvement.
Le modle relationnel peut se targuer dune forme de supriorit conceptuelle, car il
provient dune rflexion brillante et offre de grandes qualits dabstraction et de
reprsentation des donnes. Cependant, ses dfenseurs font souvent limpasse sur ses
limitations : la difficult de reprsenter efficacement tous les types de donnes et toutes les
formes dorganisation, le niveau de comptence quil demande, sa sensibilit la qualit
de la modlisation prliminaire des donnes (cest--dire sa dpendance envers les
fondations) et sa difficult en tout cas dans ses implmentations les plus classiques, car
ce dfaut nest en rien d au modle qui justement sabstrait de limplmentation physique
se distribuer sur un grand nombre de machines. En dautres termes, il sagit dun
modle hgmonique, alors que les besoins sont divers.
Paralllement, il existe un autre mouvement dont on parle un peu et qui a t nomm
NewSQL. Il sagit de concevoir des systmes distribus qui utilisent le modle relationnel
et respectent lACIDit de la transaction. Des moteurs comme NuoDB ou VoltDB sont des
moteurs dits NewSQL. NuoDB, auparavant NimbusDB, est un projet de moteur
relationnel dans le cloud qui est en version bta et qui approche dune livraison finale.
VoltDB est un projet cofond par Michael Stonebreaker, chercheur important dans le
monde des bases de donnes, puisquil est lorigine des moteurs Ingres et PostgreSQL et
ancien Chief Technical Officer (CTO) dInformix. VoltDB est sorti en version 1.0 en mai
2010 et volue en deux ditions : une community edition libre sous licence GPL v3, et une
dition entreprise commerciale.
Rcemment, le modle relationnel a retrouv un certain brillant. En 2012, Google a publi
un papier de recherche (http://research.google.com/pubs/pub38125.html) prsentant leur
nouvelle base de donnes, nomme F1. Elle est base sur une technologie prsente
comme tant le successeur de BigTable (dont nous avons pu mesurer limportance pour le
monde NoSQL dans ce livre), nomme Google Spanner. Il sagit dun moteur relationnel
distribu et transactionnel, qui se base sur Paxos et qui nutilise pas de systme de fichiers
distribu. La rplication est base sur un horodatage rendu possible par lutilisation sur les
machines qui forment le grid de modules GPS ou de modules de communication avec des
horloges atomiques pour la synchronisation des horloges.
Par rapport ces tendances, on pourrait rsumer lapproche NoSQL par cet adage dAdam
Osborne, un des pionniers de lordinateur personnel : adequacy is sufficient . Si vous
navez pas besoin de transactions et de donnes fortement structures, et que vous voulez
pouvoir monter en charge par la distribution des donnes moindre cot sur des machines
standards, vous voil arm pour faire votre choix et pour commencer explorer le moteur
qui vous convient le mieux.
Index

A
Amazons 15
arbre de Merkle 88
architecture distribue 71
Avro 65
B
bases
orientes colonnes 117
orientes documents 114
Big Data 13, 49, 118
BigTable 76, 90, 117, 225, 263
BSON (Binary Serialiazed dOcument Notation ou Binary JSON) 186
C
Cassandra 16, 64, 84, 93, 225, 257, 276, 283, 291, 299
cassandra-cli 227
CQL 228, 270
nodetool 232
CFEngine 279
cl 250, 264, 266, 269
Cloudera 129
Cobol (COmmon Business Oriented Language) 8
Codasyl (Conference on Data Systems Languages) 8
Codd, Edgar Frank 9, 13
douze rgles de Codd 10
cohrence 267
cohrence finale 87
Conception pilote par le domaine 266
Couchbase Server 261
CouchDB 37, 70, 89, 161, 237, 239, 257, 258
CouchApp 265
curl 67, 165
Cypher 244
D
Datastax 23
dfaut d<0092>impdance objet-relationnel 34
Dynamo 15, 77, 225
DynamoDB 17
E
ElasticSearch 235, 250
Erlang 162
F
Facebook 16
famille de colonnes 142, 225
G
Ganglia 301
GeoJSON 255
gestion de versions 89
Google 13, 59
BigTable 15
GFS 14
H
hachage consistant 78
Hadoop 14, 53, 129
HBase 15, 49, 142, 256
HDFS 131
hinted handoff 230
I
iftop 295
index 268
J
Java 134
JSON 250
JSON (JavaScript Object Notation) 68, 115
L
Lisp 99
M
MapReduce 44, 98, 253
memcached 211
Mmoire 271
modle
de donnes rseau 8
hirarchique 8
relationnel 9, 31, 32, 38, 118
Waterfall 29
MongoDB 36, 48, 58, 72, 107, 185, 253, 258, 268, 270, 276, 280, 298
GridFS 188
rplication 197
sharding 199
SIG 315
N
NULL 118
O
OLAP (Online Analytical Processing) 12, 50
OLTP (Online Transactional Processing) 11, 50
Oracle 22, 53
ORM (Object-Relational Mapping) 36
P
paire cl-valeur 110
paires cl-valeur 250
pidstat 296
Protocol Buffers 59