Apache CouchDB

Partie Théorique

Caractéristiques de CouchDB 
Générales

  • Développer en ERLANG                                                                                                       
    • supportant les paradigmes suivant :
      • concurrent, temps réel et distribué
      • basé sur le modèle acteur 
    • ​évaluation stricte (vs lazy // par nécessité)
    • typage dynamique fort
  • Stockage de documents JSON
  • Architecture REST : accès via le protocole HTTP
    • action avec GET, POST, PUT et DELETE
  • Matériel nécessaire : très souple 
    • utilisation sur un mobile jusqu'au cluster

Caractéristiques de CouchDB
Hardware

  • Pourquoi avoir de la ram ?​
    • utilisation du  cache du système de fichiers
  • ​​Pourquoi avoir un gros CPU (monothread...) ?
    • construction des vues
    • et non pour servir les documents
  • Pourquoi avoir du SSD ?
    • justification obscur de la documentation couchDB 
      • parce que cela permet de travailler sur des fichiers, alors qu'ils sont en cours d'écriture sans que ça coûte un bras.

Caractéristiques de CouchDB
MapReduce (1/5)

  • Dans le cas de CouchDB :
    • Il n'y a pas de langage de requête
      • Il faut définir des vues, qui sont le résultat de MapReduce
  • MapReduce
    • popularisé par Google,
    • utilisé pour traiter beaucoup de grandes données au sein d'un cluster (chaque nœud fait un traitement)

Caractéristiques de CouchDB
MapReduce (2/5)

  • Dans l'étape Map un nœud analyse un problème
    • le nœud découpe le problème en sous-problèmes,
    • et délègue les sous-problème à d'autres nœuds
      • qui peuvent en faire de même : récursivité powa \o/ 
    • les sous-problèmes sont ensuite traités par les différents nœuds à l'aide de la fonction Reduce qui
      • à un couple (clé, valeur) associe un ensemble de nouveaux couples (clé, valeur)
      • map(cle1,valeur1) → list(cle2,valeur2)

Caractéristiques de CouchDB
MapReduce (3/5)

  • Dans l'étape Reduce,
    • les feuilles font remonter leurs résultats aux parents qui les avait sollicités (jusqu'à la racine).
    • les nœuds intermédiaires calculent un résultat partiel à l'aide de la fonction Reduce qui associe toutes les valeurs correspondantes à la même clé à une unique paire (clé, valeur).
  • À la fin du processus, le nœud d'origine peut recomposer une réponse au problème qui lui avait été soumis :

    • reduce(cle2, list(valeur2))→ list(valeur2)

Caractéristiques de CouchDB
MapReduce (4/5)

  • Le modèle de programmation du MapReduce est simple et expressif
    • il y a deux fonctions : map et reduce 
      • utilisable pour traiter des données, utiliser les graphes…
    • est indépendant du système de stockage
    • peut manipuler de nombreux types de variable.
  • Le système
    • découpe les entrées, en bloc de données de même taille
    • planifie l’exécution des tâches sur les nœuds disponibles

Caractéristiques de CouchDB
MapReduce (5/5)

Subdivision <-> Agrégation

Caractéristiques de CouchDB
Multiversion Concurency Control

  • La mise à jour ne se fait pas en écrasant les données modifiées
  • Le système
    • indique que la donnée est obsolète
    • ajoute une nouvelle donnée qui correspond à une nouvelle version
      • plusieurs versions sont stockées, mais une seule est la plus récente
  • Avantage : Il n'y a pas à gérer la fragmentation de la base de données
  • Inconvénient : Il faut purger régulièrement les données obsolètes
  • Pour CouchDB, cela implique de réécrire une version complète du document à chaque MàJ. 
  • Au lieu de gérer des MàJ incrémentales constituées de petits morceaux de document liés entre eux et rangés de manière non contiguë.

Caractéristiques de CouchDB
B+ tree

  • CouchDB utilise les B+Tree pour indexer les documents
  • Un B+Tree c'est un arbre binaire 
    • avec la gestion MVCC : on ne peut qu'ajouter des éléments
      • (pas de suppression ou de modification de nœud)                         
    • et une mise à plat (rapidité de lecture)
  • Conséquence :
    • Pas de lock !
    • Toutes les feuilles contiennent les données  à exploiter
    • Des données toujours cohérentes (au moment de la lecture)
    • Consistance en cas de panne...
      • Par exemple : Il existera toujours une ancienne version exploitable si un disque est défaillant

Apache CouchDB

Partie Pratique

Partie pratique
Installation & Configuration

$ apt-get install couchdb
$ apt-get install curl
$ curl -X GET http://localhost:5984

{
  "couchdb":"Welcome",
  "uuid":"08a4ff9b3d2da0142aad1f625a1faf6c",
  "version":"1.5.0",
  "vendor":
    {
      "version":"14.04",
      "name":"Ubuntu"
    }
}

Partie pratique
Le(s) base(s) de données

$ curl -X PUT http://localhost:5984/contract (x2)
...
$ curl -X GET http://localhost:5984/_all_dbs
...
$ curl -X DELETE http://127.0.0.1:5984/contract
...
$ curl -X PUT http://localhost:5984/contract
...

Partie pratique
L'information en base - Ajout (1/3)

$ curl -X PUT http://localhost:5984/contract/contract-1 -d '{
  "id": 56405,
  "contract_name": "Formule - 1/1",
  "gamme": "Santé",
  "formule_name": "Formule ANI",
  "distributors": ["distrib-a", "distrib-b", "distrib-c"],
  "created_by": "Alan Brax",
  "created_at": "10/03/2015 à 15:42",
  "updated_by": "Bobby Wallace",
  "is_active": true
}'

# status : ok
# _id : l'identifiant
# _rev : numéro de révision 
# deux fois

$ curl -X GET http://localhost:5984/contract/contract-1

Partie pratique
L'information en base - Edition (2/3)

# MODIFICATION SIMPLE
$ curl -X PUT http://localhost:5984/contract/contract-1 -d '{
  "_id": "contract-1",
  "_rev": "2-18ba7f42526a2c1d20485e629bc67dbf",
  "id": 56405,
  "contract_name": "Formule - 1/1",
  "gamme": "Santé",
  "formule_name": "Formule ANI",
  "distributors": ["distrib-a", "distrib-b", "distrib-c"],
  "created_by": "Alan Brax",
  "created_at": "15/05/2015 à 15:42",
  "updated_by": "Bobby Wallace",
  "is_active": true
}'

#ESSAYONS AVEC LE MEME _REV ?
#ESSAYONS AVEC LE MEME _ID SANS _REV ?
#ESSAYONS EN SUPPRIMANT DES LIGNES ?

$ curl -X GET http://localhost:5984/contract/contract-1

Partie pratique
L'information en base - Suppression (3/3)

# MODIFICATION SIMPLE
$ curl -X DELETE http://localhost:5984/contract/contract-1 (2 fois)

Partie pratique
Futon - Boite à outils

GO : http://localhost:5984/_utils/

Caractéristiques de CouchDB
MapReduce (1/3)

$ curl -X PUT http://localhost:5984/test-magasin/pomme -d '{
 "item": "pomme",
 "prices": {
     "Carrefour": 1.59,
     "Auchan": 5.99,
     "Aldi": 0.79
 }
}'

$ curl -X PUT http://localhost:5984/test-magasin/orange -d '{
 "item": "orange",
 "prices": {
     "Carrefour": 1.99,
     "Auchan": 3.19,
     "Aldi": 1.09
 }
}'

$ curl -X PUT http://localhost:5984/test-magasin/banane -d '{
 "item": "banane",
 "prices": {
     "Carrefour": 1.99,
     "Price Max": 0.79,
     "Aldi": 4.22
 }
}'

Caractéristiques de CouchDB
MapReduce (2/3)

  • Allez sur Futon
    • Temporary View
    • Modification de la fonction Map()                                                                         
function(doc) {
  var shop, price, value;
  if (doc.item && doc.prices) {
      for (shop in doc.prices) {
          price = doc.prices[shop];
          value = [doc.item, shop];
          emit(price, value);
      }
  }
}
function(doc) {
  var shop, price, key;
  if (doc.item && doc.prices) {
      for (shop in doc.prices) {
          price = doc.prices[shop];
          key = [doc.item, price];
          emit(key, shop);
      }
  }
}

Caractéristiques de CouchDB
MapReduce (3/3)

  • note : il existe la possibilité d'ajouter un paramètre "rereduce" qui permet  de réduire à nouveau un résultat.        
function(doc) {
    var banane, pomme, orage;
    if (doc.item && doc.prices) {
        for (shop in doc.prices) {
            price = doc.prices[shop];
            value = [doc.item, shop];
	    emit(doc.item, price);
        }
    }
}
function (keys, prices) {
    return sum(prices);
}


function(keys, values, rereduce) {
    if (rereduce) {
        return {
            'sum': values.reduce(function(a, b) { return a + b.sum }, 0),
            'min': values.reduce(function(a, b) { return Math.min(a, b.min) }, Infinity),
            'max': values.reduce(function(a, b) { return Math.max(a, b.max) }, -Infinity),
            'count': values.reduce(function(a, b) { return a + b.count }, 0),
            'sumsqr': values.reduce(function(a, b) { return a + b.sumsqr }, 0)
        }
    } else {
        return {
            'sum': sum(values),
            'min': Math.min.apply(null, values),
            'max': Math.max.apply(null, values),
            'count': values.length,
            'sumsqr': (function() {
            var sumsqr = 0;

            values.forEach(function (value) {
                sumsqr += value * value;
            });

            return sumsqr;
            })(),
        }
    }
}

$ curl -X GET http://localhost:5984/test-magasin/_design/bobby/_view/bobby\?group\=true      

Caractéristiques de CouchDB
En plus

  • Gestion de la réplication...                                                                                                    
  • Lier des fichiers binaires (images, musique, ...)
  • Identification, gestion des utilisateurs, ...
  • ...                                                      

Merci

pour ce moment !

Apache CouchDB

By Robin Duval

Apache CouchDB

De la théorie et de la pratique !

  • 492