Base NoSql et Python

Embed Size (px)

Citation preview

Prsentation d'un nouveau produit

Les bases NoSQL et Python

Youenn Boussard

Les bases de donnes

Avant 1960 : organisation classique sous forme de fichier

1960 : 1er base de donne : militaire , hirarchique, sous forme d'arbre

1970 : Thorie sur l'algbre relationnelle de Codd

1980 : troisime gnration des sgbd : les bases de donnes orientes objets

Les donnes sont apparues avec les programmes. L'exploitation des ces donnes est la raison d'tre de l'informatique.Avec la gestion automatique des donnes, l'entreprise et les tats peuvent voluer et rivaliser avec leur concurrent l'aide de nouveaux moyens. Base de donne relationnelle : donnes dans de simple tables deux dimentions Suffisant pour toutes les applications ? Milieu des annes 80 : conviction que tout les problemes seront rsolue par les bases de donne avec leur structure logique et physique, indpendante des applications.Anne 90 avenement des technologies objets : Des estimations montrent en effet que les dveloppeurs de programmes OO utilisant des bases de donnes relationnelles passent entre 25 et 40 % de leur temps crire un code mappant les objets aux tables relationnelles.

Le dveloppement Internet

1962 Premier concept d'internet

1969 RFC

1974 Mise au point de la norme IP

1981 213 ordinateurs connects

1989 Naissance du World wide Web

2004 Web 2.0, Facebook

2006 twitter

186,7 millions de sites web

Lhistoire de lInternet remonte au dveloppement des premiers rseaux de tlcommunication. Lide dun rseau informatique, permettant aux utilisateurs de diffrents ordinateurs de communiquer, se dveloppa par de nombreuses tapes successives. 1 Licklider prsente l'ordinateur comme un outil de communication et de partage des ressources. C'est le concept de l'Internet.2 Request for comment mise en place des norme qui rgiront internet4 Ds les annes 1980, les techniques que nous reconnaissons maintenant comme les fondements de lInternet moderne commencrent se rpandre autour du globe5 - La tendance depuis 2004 est l'apparition d'applications web 2.0 pour lesquelles l'internaute joue un rle participatif.

Web 2.0 et les limites des modles relationnels

Beaucoup de donnes Digg 3TB

Facebook 50TB

Ebay 2PB

Beaucoup d'utilisateurs

Beaucoup de trafic

Et les bases relationnelles pour grer tout cela ?

Digg est un site Internet communautaire qui a pour but de faire voter les utilisateurs pour une page web intressante et propose par un utilisateurFacebook

Le cas de

Partition verticale matre-esclave avec

Lorsque l'on veux scaler une base de donnes,une premire solution peut tre le partitionnement :Vertical : une base pour les livres, une base pour les CDs, etcHorizontal : une base pour les livre de A-M et une pour les livres de N-Z,

Matre esclave

Rplication Matre esclaveUn unique matre

Un ou plusieurs esclave

Toute les critures vont sur le matre, rpliquer sur les esclaves

Les lectures sont rparties entre les diffrents matres et esclaves

Cela impliqueLe matre est critique

Le matre est le point d'engorgement du systme

Partition Horizontale

Rparties sur plusieurs noeuds

Les jointures sont dportes au niveau de l'application

Cela impliqueOn n'est plus relationnel

Le fonctionnel devient compliqu

La maintenance aussi !!

On renonce la normalisation des donnes Frais de gestion importanteLa scabilit a un coup qui devient important

Et la disponibilit !!

Table Diggs Id

Itemid

Userid

Digdate

Table Friends Id

UserId

UserName

FriendId

FriendName

Mutual

Date_created

Des centaines de millions de lignesTable Diggs Id

Itemid

Userid

Digdate

Des millions de lignesProbleme : Afficherles amis qui on cliqu sur l'un de mes diggs (fonctionnalitdu green badge)

14sec

Sytme distribu : Trois tats

C comme Consistence

A comme Availability (Disponibilit)

P comme Partition tolrance

Dr. Eric Brewer

CAP THEOREM =On ne peut avoir que 2 tats en simultane dans un systme
distribuconsistence -> tout les noeuds ont les meme donnes en meme tempsdisponible -> le systeme est toujours disponible tant qu'il y a un noeudtolrance la partition -> le systeme continue fonctionner malgr la perte de message

ACID contre BASE

Atomique

Cohrente

Isole

Durable

Basically Available

Soft state

Eventually consistent

Certaines donnes nous paraissent logiques d'tre consistantes mais cela est souvent du notre inertie d'esprit. Prenons le cas d'une valeur indiquant le stock d'un article. Si deux serveurs ont des valeurs non consistantes, il peut arriver qu'un serveur considre qu'il en reste un alors qu'un autre qui a tait mis jour, sait qu'il n'en reste plus. Lorsque vous faites un achat et si par malchance vous acheter un livre qui n'est plus en stock, le site marchand deux possibilits : vous rembourser ou rapprovisionner le stock (je ne sais pas vous, mais cela m'est dj arriv de recevoir un mail en disant que le produit tait puis,aprs l'avoir command)les sites ont fait leur choix ! Amazon a d'ailleurs constat qu'un dixime de seconde de latence leur fait diminuer les ventes de 1%, et Google a remarqu qu'une demi seconde de latence fait chuter le trafic d'un cinquime.

Non relationnelle

Distribue

Open source

Scalable horizontablement

Une nouvelle Gnration de base de donne

Nosql : not only sql

schema-free, easy replication support, simple API, eventually consistent / BASE (not ACID)

Les diffrents types de base de donne :Relationnel ACIDKey-value support get, put, delete sur leur cleOriente colonne utilise des tables mais pas de joins, les donnes sont stockes par colonne oppos aux traditionnels donnes stock en ligneOriente document stocke des documents structure en JSON ou en XML : facil de mapper avec des langages oriente objets

CA : ont des difficults avec les partitions et doivent rpliquer leurs donnes (base de donne)CP : ont des difficults avec la disponibilits en gardant consistante leurs donnes sur l'ensemble des noeudsAP : eventuellement consitant avec la replication et les verifications.

CouchDB est

Orient document Pas de schma, reprsentation des donnes telle quelle

Accessible via RESTful

Distribu, rplication incrmental, rsolution de conflit bi directionnel

Donne indexable et requetable suivant des vues

Ecrit en

Elle est conue avant tout pour les applications web

Chaque document est compos de proprits. Il ny a aucune contrainte sur le nombre de proprits dun document, sur le type de ces proprits...

Le protocole permettant daccder un serveur CouchDB est bas sur HTTP, avec une interface REST.

Erlang est langage fonctionnel concurrent, temps rel et distribu bas sur le modle d'acteur. Il possde des fonctionnalits de tolrance aux pannes et de mise jour du code chaud permettant le dveloppement d'applications haute disponibilit.

Un document

Un document est un objet contenant un ensemble de cls valeurs

{"_id": "j_aime_le_mouvement_no_sql" "_rev": "1-1" "Subject": "J'aime le mouvement no sql" "Author": "Youyou" "PostedDate": "5/23/2006" "Tags": ["database", "nosql"]"Body": "Je prsente aujourd'hui une prsentation!!."Une base de donnes couchdb est une collection plat de ces documents

Il y a trois cls qui sont imposes par CouchDB : _id : lidentifiant unique du document ; _rev : le numro de rvision du document, gr automatiquement par le moteur CouchDB ; _attachments : les ventuels fichiers attachs ce document.Stocke sous la forme de texte json ( Javascript Standard Object Notation) srialisation d'objetune chane de caractres doit tre mise entre quotes : "ceci est un string". un objet (qui supporte des donnes de type "cl" => valeur") est reprsent par des accolades : { "key1": "value1", "key2":"value2" }. une liste de valeurs (un tableau) est reprsent par des crochets : [ "value1","value2"]. JSON supporte les boolens : true et false ainsi que null. JSON supporte les nombres flottants : 21.34576.MVCC : multiversion concurrency control

RESTFul API

REST est bas sur le protocole HTTPLecture : GET /somedatabase/some_doc_id

Ecriture / update : PUT

Crer : POST

Supprimer : DELETE

PUT /somedatabase/some_doc_id HTTP/1.0Content-Length: 245Content-Type: application/json

Body

REST : Representational State Transfer, est connu comme une alternative simple au protocole SOAP, pour interfacer des web services. Rest nest pas un protocole, cest un style darchitecture.

Robuste

N'crase pas une donne commit

Si le serveur tombe, il faut juste redmarrer CouchDB pas de repair

On peut prendre des snapshots avec des simples cp

Plusieurs niveaux de durabilit : Choix entre synchroniser toutes les mises jours ou la demande

CouchDB uses an "optimistic concurrency" modelIe Couchdb rejete le document si celui si n'est pas celui que vous avez envoyer !Retrieve the document, take note of the _rev property that CouchDB sends alongDecrement the quantity field, if it's greater than zeroSend the updated document back, using the _rev propertyIf the _rev matches the currently stored number, be done!If there's a conflict (when _rev doesn't match), retrieve the newest document version

Vues

Mthodes pour aggrger et requeter les documents de la base de donne

Les vues sont dfinies par des documents spciaux les designs documents

Les vues sont crites en javascript.

Pour maintenir des performances sur les vues, le moteur de vues maintient des indexes sous forme btree

MapReduce

Introduit par Google

2 tapeEtape Map itre sur une liste d'lments indpendants et accomplit une opration spcifique sur chaque lment

function(doc){}

Etape Reduce prend une liste et combine les lments selon un algorithme particulier

fonction(keys, values, rereduce){}

MapPar exemple, considrons une liste de notes d'examen, o chaque note est 1 point trop leve. Une fonction map de s - 1 pourrait tre applique sur chaque note s.

Reduce comment faire si l'on souhaite connatre la moyenne de la classe ? On peut dfinir une fonction de rduction qui diminue de moiti la liste par ajout d'une entre dans la liste des voisins, rcursivement, on continue jusqu' ce qu'il y ait seulement une (grosse) entre, et divise la somme totale par l'entre originale d'lments pour avoir la moyenne).

{ "_id":"_design/company", "_rev":"12345", "language": "javascript", "views": { "all": { "map": "function(doc) { if (doc.Type == 'customer') emit(null, doc) }" }, "by_lastname": { "map": "function(doc) { if (doc.Type == 'customer') emit(doc.LastName, doc) }" }, "total_purchases": { "map": "function(doc) { if (doc.Type == 'purchase') emit(doc.Customer, doc.Amount) }", "reduce": "function(keys, values) { return sum(values) }" } }}

Exemple d'une vue


Exemple de map/reduce

couchdb-python

Ct clientcouchdb.client client pour s'interfacer avec des servers couchdb

couchdb.design pour grer les design documents

couchdb.mapping fournit des mappings entre les document json et les objets python

Cot serveurcouchdb.view pour crire des vues en python plutt qu'en javascript

couchdb.client.Server

Reprsentation d'un server CouchDB>>> server = Server('http://localhost:5984/')

Pour crer une base de donnes : create >>> server.create('python-tests')

Pour accder une base de donnes >>> server['mabase']

Pour supprimer une base de donnes>>> del server['mabase']

couchdb.client.Database

Cration d'un nouveau document>>> server = couchdb.client.Server()>>> db = server.create('test')>>> doc_id, doc_rev = db.save({'type' : 'contact', 'name': 'yo'})

Rcuperation d'un document>>> db[doc_id]

Un document est comme dictionnaire>>> db[doc_id]['type']'contact'

couchdb.client.ViewResults

Reprsentation d'une vue (permanent ou temporaire)>>> map_fun = '''function(doc) {emit([doc.type, doc.name], doc.name); }'''>>> results = db.query(map_fun)

En option, on peut envoyer tous les paramtres d'une vue>>> db.query(map_fun, count = 10 , skip = 5, descending = true)

On peut utiliser les slices python pour positionner des startkeys et les endkeys>>> results[keystart:keyend]

Mapper les documents Couchdb

Permet de mapper des structures json avec du python et vice versa>>> Class Person(couchdb.mapping.Document): name = couchdb.mapping.TextField() age = couchdb.mapping.IntegerField() modified = couchdb.mapping.DateTimeField(default=datetime.now)>>> person = Person(name='youyou', age = 32)>>> person.store(db)>>> Person.load(db, 'youyou').rev....

couchdb.mapping.ViewField

Pour associer une vue un attribut d'une classeclass Person(Document): by_name = ViewField('people', '''\

... function(doc) { ... emit(doc.name, doc); ... }''')

>>> Person.by_name(db, count=3)

couchdbkit

Bas sur restkit , librairie http qui n'est pas bas sur urllib2 ou httplib

couchdbkit.client API client vers couchdb

Mapping dynamique des documents

Extension django

couchdbkit.consumer Ecoute les changements effectus sur la base de donnes

couchdbkit.loaders pousse des fichiers de vues sur couchdb

CouchApp

Utilitaire de dploiement d'application pour couchDB

Ecrit en python

Cre un squellete d'application

Gnre du code l'aide de macros

Dploie les applications sur des serveurs CouchDB

Introduction

Utiliser en production par Digg, FaceBook, Twitter, Reddit

Tolrant la panne

Dcentraliser

Sous contrle

Modle de donnes efficient et efficace

Elastique

Durable

1 Le plus gros cluster cassandra utilise 100 TB de donne rpartie sur 150 machine2 Les donne sont automatiquement repliqus dur des mutliples noeud . La replication entre plusieurs data center est supporter .Les noeuds mort sont remplacer sans rupture de service3 Tout les noeuds sont identiques.Pas de point de failure4 Vous avez le choix entre une replication assynchrone et synchone pour chaque mis jour5 Modele oriente colonne5 les lectures et les critures augmente lineairement lorsqu'on ajoute des machines6 Procedure via un commitlog de ne perdre aucune donne

Modle de donnes

ColonneLa plus petite unit de donnes dans cassandra

C'est un triplet

{ // this is a column name: "mailAddress", value: "[email protected]", timestamp: 123456789}

Ou plus simplement

emailAdress : "[email protected]"

Modle de donnes

Super ColonneC'est un tuple qui a un nom et une valeur (comme la colonne)

Mais la valeur est une liste de colonnes

{ // this is a SuperColumn name: "homeAddress", // with an infinite list of Columns value: { // note the keys is the name of the Column street: {name: "street", value: "1234 x street", timestamp: 123456789}, city: {name: "city", value: "san francisco", timestamp: 123456789}, zip: {name: "zip", value: "94107", timestamp: 123456789}, }}

Famille de colonnes

Une famille de colonnes est une structure qui contient une liste de lignes (comme les bases de donnes)

UserProfile = { // this is a ColumnFamily phatduckk: { // this is the key to this Row inside the CF // now we have an infinite # of columns in this row username: "phatduckk", email: "[email protected]", phone: "(900) 976-6666" }, // end row ieure: { // this is the key to another row in the CF // now we have another infinite # of columns in this row username: "ieure", email: "[email protected]", phone: "(888) 555-1212" age: "66", gender: "undecided" },}

Modle de donnes

Super Famille de colonnesUne Famille de colonne peut tre super ou standard

Super c'est que les lignes contiennent des super colonnes aka cle : list( colonne)

Une ligne est une liste de colonnes ou de super colonnes identifies par une cl

Super famille de colonne

AddressBook = { // this is a ColumnFamily of type Super phatduckk: { // this is the key to this row inside the Super CF // the key here is the name of the owner of the address book

// now we have an infinite # of super columns in this row // the keys inside the row are the names for the SuperColumns // each of these SuperColumns is an address book entry friend1: {street: "8th street", zip: "90210", city: "Beverley Hills", state: "CA"},

// this is the address book entry for John in phatduckk's address book John: {street: "Howard street", zip: "94404", city: "FC", state: "CA"}, Kim: {street: "X street", zip: "87876", city: "Balls", state: "VA"}, Tod: {street: "Jerry street", zip: "54556", city: "Cartoon", state: "CO"}, Bob: {street: "Q Blvd", zip: "24252", city: "Nowhere", state: "MN"}, ... // we can have an infinite # of ScuperColumns (aka address book entries) }, // end row ieure: { // this is the key to another row in the Super CF // all the address book entries for ieure joey: {street: "A ave", zip: "55485", city: "Hell", state: "NV"}, William: {street: "Armpit Dr", zip: "93301", city: "Bakersfield", state: "CA"}, },}

L'ensemble des familles de colonnes et des supers familles de colonnes constituent un espace de cls (keyspace)

Modle de donnes

Les cls sont tries lorsqu'elle sont insres dans le modle

Ce tri est respect quand on recupre les lments le model doit tre conu en fonction de cela

Les lignes sont tries par leur nom

Les options de tri se font au niveau des familles de colonnes

Twissandra : un twitter like

http://github.com/ericflo/twissandra

Cassandra par l'exemple en python

La faon de structurer les donnes doit tre proche de la faon pour lesquelles on doit les rcuprer pour les afficher

Twissandra : un twitter like

User colonne family

La cl de la ligne est l'id de l'utilisateur

User = { 'a4a70900-24e1-11df-8924-001ff3591711': { 'id': 'a4a70900-24e1-11df-8924-001ff3591711', 'username': 'ericflo', 'password': '****', },}

Twissandra : un twitter like

Les amis et les adeptes sont indexs par le user id

Friends = { 'a4a70900-24e1-11df-8924-001ff3591711': { # friend id: timestamp of when the friendship was added '10cf667c-24e2-11df-8924-001ff3591711': '1267413962580791', '343d5db2-24e2-11df-8924-001ff3591711': '1267413990076949', '3f22b5f6-24e2-11df-8924-001ff3591711': '1267414008133277', },}

Twissandra : un twitter like

Les tweets sont stokes comme les utilisateurs

Tweet = { '7561a442-24e2-11df-8924-001ff3591711': { 'id': '89da3178-24e2-11df-8924-001ff3591711', 'user_id': 'a4a70900-24e1-11df-8924-001ff3591711', 'body': 'Trying out Twissandra. This is awesome!', '_ts': '1267414173047880', },}

Twissandra : un twitter like

Les tweets sont stokes comme les utilisateurs

Tweet = { '7561a442-24e2-11df-8924-001ff3591711': { 'id': '89da3178-24e2-11df-8924-001ff3591711', 'user_id': 'a4a70900-24e1-11df-8924-001ff3591711', 'body': 'Trying out Twissandra. This is awesome!', '_ts': '1267414173047880', },}

Twissandra : un twitter like

La ligne de temps et la ligne des utilisateurs doivent afficher les tweets par ordre d'arrive

Timeline = { 'a4a70900-24e1-11df-8924-001ff3591711': { # timestamp of tweet: tweet id 1267414247561777: '7561a442-24e2-11df-8924-001ff3591711', 1267414277402340: 'f0c8d718-24e2-11df-8924-001ff3591711', 1267414305866969: 'f9e6d804-24e2-11df-8924-001ff3591711', 1267414319522925: '02ccb5ec-24e3-11df-8924-001ff3591711', },}Userline = { 'a4a70900-24e1-11df-8924-001ff3591711': { # timestamp of tweet: tweet id 1267414247561777: '7561a442-24e2-11df-8924-001ff3591711', 1267414277402340: 'f0c8d718-24e2-11df-8924-001ff3591711', 1267414305866969: 'f9e6d804-24e2-11df-8924-001ff3591711', 1267414319522925: '02ccb5ec-24e3-11df-8924-001ff3591711', },}

Twissandra : un twitter like

Twissandra utilise pycassa , API de haut niveau pour accder cassandra

Pycassa utilise thrift, un framework d'appel de procdure distance

Thrift gere 12 languages dont python

pycassa.columnfamily.ColumnFamily

Opration sur la famille de colonne

>>> cf = pycassa.ColumnFamily(client, 'UserName')

## insertion d'une colonne>>> cf.insert('user1', {'id': 'User'})1261349837816957

>>> cf.get('foo'){'column1': 'val1'}

## inserion de plusieurs colonne>>> cf.insert('user2', {'id': 'User', 'name': 'Name User'})

## recuperation des lignes>>> list(cf.get_range())

pycassa.columnfamilymap.ColumnFamilyMap

Pour mapper des objets avec des colonnes

>>> class Test(object):... string_column = pycassa.String(default='Your Default')... int_str_column = pycassa.IntString(default=5)... float_str_column = pycassa.FloatString(default=8.0)... float_column = pycassa.Float64(default=0.0)... datetime_str_column = pycassa.DateTimeString() # default=None

>>> Test.objects = pycassa.ColumnFamilyMap(Test, cf)

>>> t = Test()>>> t.key = 'maptest'>>> t.string_column = 'string test'>>> t.int_str_column = 18>>> t.float_column = t.float_str_column = 35.8>>> from datetime import datetime>>> t.datetime_str_column = datetime.now()>>> Test.objects.insert(t)1261395560186855

Les autres librairies python
pour cassandra

Tragedy: http://github.com/enki/tragedy/

Lazy Boy: http://github.com/digg/lazyboy/tree/master

Telephus: http://github.com/driftx/Telephus/tree/master (Twisted)

Neo4J

Modle de donnes sous la forme de graphe

Embarqu

Stock sur disque

Scalable

Framework de traverse

API simple et pratique

1 Au lieu de travailler sur des statc et rigide table avec des lignes et des colonnes vous travailler sur un graph flexible qui s'adapte a vos besoin en ayant a votre disposition des noeud , des relation et des proprits.

2 C'est l'application qui embarque la base de donne neo4j

3 Une gestion de stokage optimiser pour stocker plusieurs billion de noeud, de relaction , de proprietes. La base de donne peut etre rpartie sur plusieurs disque

4 framework performant de travers.

Le modele de donnes : Un graphe
orient

Reprsentation sous la forme de:Noeuds

Relations entre les noeuds

De proprits (au niveau des relations et noeuds)

Exemple : modlisation des familles de produits

Rgle mtierUne famille peut tre une sous-famille

Dans une famille il peut y avoir des produits

Chaque famille de produits peut avoir des proprits

Exemple d'une instance de la base

Neo4j.py : binding python pour Neo4j

Peut tre utilis indiffrement avecJython

Cpython

Ouvrir une base de donnes neo4j

graphdb = neo4j.GraphDatabase("/neo/db/path", classpath=["/a/newer/kernel.jar"], jvm="/usr/lib/jvm.so")

Neo4j.py : binding python pour Neo4j

Crer une noeud

>>> mac_node = graphdb.node(Name='MacBook')## ajouter des pro>>> mac_node['Name']'MacBook'Crer une relation entre les noeuds

>>> laptop_node = graphdb.node(Name='Laptop'')## la mac est un produit de la famille des laptop_node>>> laptop_node.PRODUCTS(mac_node)

Neo4j.py : binding python pour Neo4

TraversalsSont dfinis en crant une classe qui hrite de neo4j.Traversal

Un objet Traversal doit dfinir les attributs suivants:Types : la liste des relations qui vont tre traverses pendant la travers

Order : l'ordre de traverse

Stop : la condition de d'arrt

Returnable : La dfinition des noeuds qui vont tre retourns

Neo4j.py : binding python pour Neo4

class SubCategoryProducts(neo4j.Traversal): "Traverser that yields all products in a category and its sub categories." types = [neo4j.Outgoing.SUBCATEGORY, neo4j.Outgoing.PRODUCT] def isReturnable(self, pos): if pos.is_start: return False return pos.last_relationship.type == 'PRODUCT'

## get products of laptop_node>>> p = [x for x in SubCategoryProducts(laptop_node)]

Rfrences

NoSQLhttp://www.julianbrowne.com/article/viewer/brewers-cap-theorem

http://natishalom.typepad.com/nati_shaloms_blog/2009/12/the-common-principles-behind-the-nosql-alternatives.html

http://horicky.blogspot.com/2009/11/nosql-patterns.html

References

CouchDBhttp://www.unixgarden.com/index.php/web/couchdb-la-base-de-donnees-qui-change-tout

http://davidwatson.org/2008/02/python-couchdb-rocks.html

http://wiki.apache.org/couchdb/Introduction_to_CouchDB_views

http://labs.mudynamics.com/wp-content/uploads/2009/04/icouch.html

http://horicky.blogspot.com/2008/10/couchdb-cluster.html

Rfrences

Cassandrahttp://www.slideshare.net/Eweaver/cassandra-presentation-at-nosql

http://spyced.blogspot.com/2009/03/why-i-like-cassandra.html

http://arin.me/blog/wtf-is-a-supercolumn-cassandra-data-model

http://wiki.apache.org/cassandra/ThriftExamples#Python

ttp://www.slideshare.net/stuhood/cassandra-talk-austin-jug

http://www.rackspacecloud.com/blog/2010/05/12/cassandra-by-example/

Rfrences

Neo4Jhttp://www.slideshare.net/thobe/persistent-graphs-in-python-with-neo4j

http://python.mirocommunity.org/video/1597/pycon-2010-persistent-graphs-i

http://blog.neo4j.org/2010/03/modeling-categories-in-graph-database.html