Vitesse
Volume
Scalabilité de MongoDB
• Cluster shardé de plus de 250 serveurs
• Plus de 300 000 opérations par seconde, 200 serveurs, 5.5 milliards de documents
• 12 shards, 108 serveurs, 10 TB de données, 12 milliards de documents, croissance de 1.5M docs par an
• 100 applications déployées sur plus de 1 000 nœuds, 20 milliards d’opérations par jour
5
Better Data Locality In-Memory Caching In-Place Updates
Performance
vs.
Relational MongoDB
Facteurs de succès
Stockage : vitesse des accès disque, IOPS
RAM : capacité suffisante pour données actives et index
Requêtes : utilisation efficace d’index et projections
Remove : opération la plus coûteuse
Update : attention aux déplacements
Real-time ou bulk
Index : Ni trop, ni trop peu
Sharding : stratégie et clé de sharding
Ressources : ne partez pas seuls !
Outils
MongoDB Management Services (MMS)mongoperf : Test la capacité du disquemongostat : Activité des mongodmongotop : Activité des collections
Profiler : db.setProfilingLevel(0|1|2, slowms=100ms)
Explain : db.scores.find({student:0}).explain()
mTools : https://github.com/rueckstiess/mtools- mlogfilter, mloginfo, mplotqueries, mlogvis
…
mtools mlogvis
mongoperf
Sharding
Données de travail trop volumineuses
Débit I/O insuffisant
Modèle de scalabilité
Vertical Horizontal
Shard
• Un shard est un nœud du cluster• Il peut être un simple mongod ou un replica set
Stockage des métadonnées du cluster
• Config Server– Stocke les définitions des intervalles (chunks)
et leur localisation– 1 config server en dév, 3 en production– Ce n’est pas un replica set
Routing and Managing Data
• mongos– Agit comme routeur et équilibreur de charge– Aucune donnée stockée, processus light– On peut en avoir un ou plusieurs– Localisé avec l’application ou sur serveur dédié
Sharding infrastructure
Config
Config
Config
Partionnement de la donnée
Partionnement de la donnée
Activation du sharding sur la db
L’utilisateur définit une clé de sharding (fonctionnelle ou hash) par collection
La clé de sharding définit un ensemble ordonné de données
Chaque valeur de clé appartient à un intervalle
Les intervalles sont scindés et déplacés au fil du temps
Chunk initial
Découpage (split) des Chunks
Un chunk est scindé lorsqu’il atteint la taille maximum (64 Mo par défaut)
On ne peut découper qu’entre 2 valeurs distinctes
Un split n’entraine pas forcément de déplacement
Initialement 1 seul chunk
Les chunks sont scindés automatiquement lorsqu’ils atteignent la taille limite (64 Mo par défaut)
Les chuncks sont déplacés automatiquement
Déplacement des Chuncks
Nombre de Chunks Seuil de migration
< 20 chuncks 2
20 à 79 chuncks 4
> 80 chuncks 8
Le balancer d’un des mongos s’approprie le balancer lockUn seul lock une seule migration à la foisStatus du lock:
use configdb.locks.find({ _id: “balancer” })
Déplacement des Chuncks
mongos envoie une commande moveChunk à la source
Le shard source notifie le shard de destination
Le shard de destination construit les index nécessaires
Le shard de destination récupère les documents depuis la source
Les documents reste accessibles en R/W sur la source
Déplacement des Chuncks
Une fois les documents copiés
- Processus de synchronisation pour vérifier la transmission
- Mise à jour des config servers
Déplacement des Chuncks
Le shard source supprime les données déplacées
– Tous les curseurs ouverts doivent être fermés ou en timeout
– Curseurs avec NoTimeout empêche la libération du lock
Le mongos libère le lock
Déplacement des Chuncks
Routage des requêtes
Routage des requêtes : Targeted Query
• Des éléments de la clé de sharding sont présents dans la requêtes
• Le mongos peut cibler un sous ensemble de shard
• Une partie des shards n’est pas sollicité
Routage des requêtes : Scatter/Gather
• Le mongos ne peut pas sélectionner un sous ensemble de shard
• La requête est envoyée à l’ensemble des shards
• La fusion des résultats et le tri final sont effectués sur le shard primaire de la base de données
• Aggrégation : pipeline est découpé en 2 à partir du premier $group ou $sort
Choix de clé de sharding
• La clé de sharding est immutable• Les valeurs de la clé sont immutables• La clé de sharding doit être indexée• Taille limitée à 512 octets• Clé de sharding requise pour insertions• Clé de sharding utilisée pour le routage des
requête : critique pour la peformance
Choix de clé de sharding
• Cardinalité• Distribution des écritures• Isolation des requêtes• Performance des tris
Shard Key Hash
• Pros:– Très bonne distribution des écritures
• Cons:– Mise à jour des données et maintenance des index coûteuses
– Requêtes sur des intervalles et tris scatter gather
Shard 1
mongos
Shard 2 Shard 3 Shard N
Shard Key à faible cardinalité
• Peut introduire l’effet « jumbo chunks »• Equilibre de la charge incertain• Exemple : booléen, année de naissance…
Shard 1
mongos
Shard 2 Shard 3 Shard N
[ a, b[ [ c, d[
Shard Key Monotonique
• Clé toujours croissante ou toujours décroissante• Introduit des "hot spots" à l’insertion • Vitesse d’insertion non liée au nombre de shards• Examples: timestamps, _id
Shard 1
mongos
Shard 2 Shard 3 Shard N
[ ISODate(…), $maxKey )
Optimisations
Pre Splitting
• Permet de prédéfinir le partitionnement de la
collection : évite scissions et déplacements
• Cas d’ingestion massive de données
• Lorsque la collection est vide uniquement
for ( var x=97; x<97+26; x++ ) { //a, b, c, d….
for( var y=97; y<97+26; y+=6 ) { //a, g, m, s, y
var prefix = String.fromCharCode(x)+String.fromCharCode(y);
//prefix = aa, ag, am, as, ay, ba, bg…
db.runCommand( { split : "myapp.users" , middle : { email : prefix } } );
}
}
Tag-aware sharding
• Découpage macroscopique du cluster
• Splits et Move ont toujours lieu, en respectant les contraintes
• Un tag définit un intervalle • Recouvre plusieurs chunks• Recouvre plusieurs shards
sh.addShardTag("shard0000", "NYC")
sh.addShardTag("shard0001", "NYC")
sh.addShardTag("shard0002", "NYC")
sh.addShardTag("shard0003", "SFO")
sh.addTagRange("records.users", { zipcode: "10001" }, { zipcode: "10281" }, "NYC")
sh.addTagRange("records.users", { zipcode: "11201" }, { zipcode: "11240" }, "NYC")
sh.addTagRange("records.users", { zipcode: "94102" }, { zipcode: "94135" }, "SFO")
Read Global/Write Local
Primary:NYC
Secondary:NYC
Primary:LON
Primary:SYD
Secondary:LON
Secondary:NYC
Secondary:SYD
Secondary:LON
Secondary:SYD
Pilotage du balancer
Pilotage manuel Arrêt pendant les imports de masse
sh.startBalancer() / sh.stopBalancer()
Scheduling Fonctionnement pendant les périodes calmes
db.settings.update({ _id : "balancer" }, { $set : { activeWindow :
{ start : "23:00", stop : "6:00" } } }, true )
Conclusion
Conclusion
#1 – Modélisation
#2 – Index
#3 – IOPS et RAM
#4 – Sharding… avec la bonne clé
#5 – Monitoring
#6 – Améliorations 2.8
#7 – Nous pouvons vous aider