Cassandra techniques de modelisation avancee
Upcoming SlideShare
Loading in...5
×
 

Cassandra techniques de modelisation avancee

on

  • 784 views

DevoxxFR2014 Université sur les techniques de modélisation avancée dans Cassandra

DevoxxFR2014 Université sur les techniques de modélisation avancée dans Cassandra

Statistics

Views

Total Views
784
Views on SlideShare
771
Embed Views
13

Actions

Likes
1
Downloads
16
Comments
0

1 Embed 13

https://twitter.com 13

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Cassandra techniques de modelisation avancee Cassandra techniques de modelisation avancee Presentation Transcript

  • @doanduyhai#C*ModelisationAvancee Cassandra Techniques de modélisation avancée
  • @doanduyhai#C*ModelisationAvancee DuyHai DOAN Le jour: + + conseil Le soir: Cassandra + Achilles @doanduyhai doanduyhai@gmail.com doanduyhai Développeur Freelance Java/Cassandra
  • @doanduyhai#C*ModelisationAvancee Agenda Modèle de données Architecture technique CQL3 en détail Techniques de modélisation de base 3
  • @doanduyhai#C*ModelisationAvancee Agenda Techniques de modélisation avancée Modélisations exotiques Les anti-patterns Les index secondaires <Futur> C* 4
  • @doanduyhai#C*ModelisationAvancee MODÈLE DE DONNÉES Concepts Accès aux données Le type « composite »
  • @doanduyhai#C*ModelisationAvancee Table/Column Family Stockage physique  ligne physique = partition  clé de partition (#partition)  clé de colonne (#colonne)  cellule #partition1 #col1 #col2 #col3 #col4 cellule1 cellule2 cellule3 cellule4 #partition2 #col1 #col2 #col3 cellule1 cellule2 cellule3 #partition3 #col1 #col2 cellule1 cellule2 #partition4 #col1 #col2 #col3 #col4 … cellule1 cellule2 cellule3 cellule4 … 6
  • @doanduyhai#C*ModelisationAvancee Keyspace Ensemble de column family (table) Keyspace system  metadata sur les keyspaces et tables Keyspace system_auth  authentification & contrôle d’accès Cassandra Keyspace Table 1 n 1 n 7
  • @doanduyhai#C*ModelisationAvancee Distribution Aléatoire: hash de #partition → token = hash(#p) Hash: [0, 2127-1] Chaque nœud: 1/8 8 n1 n2 n3 n4 n5 n6 n7 n8
  • @doanduyhai#C*ModelisationAvancee Table ≈ Map<#p,SortedMap<#col,cellule>> Vue logique SortedMap<tokenp,…> 9
  • @doanduyhai#C*ModelisationAvancee Table ≈ Map<#p,SortedMap<#col,cellule>> SortedMap<#col,cellule>> Vue logique Unicité Tri SortedMap<tokenp,…> 10
  • @doanduyhai#C*ModelisationAvancee Vue logique Map<#p,SortedMap<#col,cellule>> → cellule par (#partition + #colonne) très rapide #partition1 #col1 #col2 #col3 #col4 … cellule1 cellule2 cellule3 cellule4 … 11
  • @doanduyhai#C*ModelisationAvancee Vue logique Map<#p,SortedMap<#col,cellule>> → plage de #colonnes (triées) par #partition très rapide #partition1 #col1 #col2 #col3 #col4 … cellule1 cellule2 cellule3 cellule4 … 12
  • @doanduyhai#C*ModelisationAvancee Vue logique Map<#p,SortedMap<#col,cellule>> → plage de partitions par #partition très lent    13
  • @doanduyhai#C*ModelisationAvancee Vue logique Map<#p,SortedMap<#col,cellule>> Cellules vides Données possible dans #colonne  limite: 64K #partition1 #col1 #col2 #col3 #col4 Ø Ø Ø Ø 14
  • @doanduyhai#C*ModelisationAvancee Types Supportés  int, long, string, float, double, byte (blob)  uuid, time uuid  timestamp  counter  #partition, #colonne & cellule Tri sur #colonne: ordre naturel du type 15
  • @doanduyhai#C*ModelisationAvancee Démo cassandra-cli : « stockage_physique »
  • @doanduyhai#C*ModelisationAvancee Insertion Chargement simple Slice query Accès aux données 17 INSERT INTO xxx(partition,colonne,cellule) VALUES(#p,#col,valeur) SELECT cellule FROM xxx WHERE partition = #p AND colonne = #col SELECT * FROM xxx WHERE partition = #p AND colonne ≥ #c1 AND colonne ≤ #c2 LIMIT n
  • @doanduyhai#C*ModelisationAvancee Slice query  #partition = superhéros  catwoman ≤ #col ≤ superman  décroissant  n = 3 Accès aux données superhéros batman catwoman flash green lantern superman Ø Ø Ø Ø Ø 3 18
  • @doanduyhai#C*ModelisationAvancee Multiget slice query   slice query pour un ensemble de {#p1, #p2,…} donné  équivalent à → #p1, entre: c1et c2 && → #p2, entre: c1et c2 && …  avantage / inconvénient Accès aux données 19
  • @doanduyhai#C*ModelisationAvancee #Colonne en multiple composants  type1:type2:type3  tri successif par composant Type « composite » 20
  • @doanduyhai#C*ModelisationAvancee #Colonne en multiple composants  type1:type2:type3  tri successif par composant Map<#partition, SortedMap<#comp1,< SortedMap<#comp2,< … SortedMap<#compn,Cellule>…> Type « composite » 21
  • @doanduyhai#C*ModelisationAvancee Exemple: table hygrometrie #partition → ville #colonne → LongType:UTF8Type  LongType: date de mesure en Unix time  UTF8Type: type de mesure celulle → DoubleType Map<ville,SortedMap<dateUnix,SortedMap<type,valeur>>> Type « composite » 22
  • @doanduyhai#C*ModelisationAvancee Démo cassandra-cli : « hygrometrie »
  • @doanduyhai#C*ModelisationAvancee Slice query avec « composite » Requêtes  relevé par ville, date et type #p = Paris, #comp1 = date1, #comp2 = temperature  relevés par ville et date #p = Paris, #comp1 = date1  relevés par ville et tranche de dates #p = Paris, #comp1 ≥ date1 & #comp1 ≤ date2 24
  • @doanduyhai#C*ModelisationAvancee Slice query avec « composite » Requêtes  relevé par ville et type #p = Paris, #comp2 = temperature Map<ville,SortedMap<date,SortedMap<type,valeur>>>  25
  • @doanduyhai#C*ModelisationAvancee Q & R  
  • @doanduyhai#C*ModelisationAvancee ARCHITECTURE TECHNIQUE Système de fichiers Chemin de lecture/écriture Compaction
  • @doanduyhai#C*ModelisationAvancee Mémoire Off-Heap Disque Column Family User Row Cache Mémoire JVM Heap Partition Key Cache Commit log1 … Key Index Sample Compression offset Bloom Filter SStable 3 Système de fichiers SStable 2SStable 1 Commit log 2 Commit logn Key Index Sample Compression offset Bloom Filter Key Index Sample Compression offset Bloom Filter 28
  • @doanduyhai#C*ModelisationAvancee Système de fichiers Format  <keyspace>-<column family>-<version>-<génération>-<composant>.db SSTables test-user-ic-1-Data.db → snapshot d’une SSTable à un instant t Méta-données test-user-ic-1-CompressionInfo.db → offset des données compressées test-user-ic-1-CRC.db → CRC des données non compressées 29
  • @doanduyhai#C*ModelisationAvancee Système de fichiers Format  <keyspace>-<column family>-<version>-<génération>-<composant>.db Méta-données test-user-ic-1-Filter.db → filtre de Bloom test-user-ic-1-Index.db → index des offset de #partition dans le SSTable test-user-ic-1-Statistics.db → statistiques test-user-ic-1-Summary.db → échantillon des offsets de #partition test-user-ic-1-TOC.txt 30
  • @doanduyhai#C*ModelisationAvancee Format des fichiers #p (user001) Longueur ligne Index de colonne * Tombstone Nb de colonnes Colonne1/Cellule1 …. ColonneN/CelluleN #p (user350) Longueur ligne Index de colonne * Tombstone Nb de colonnes Colonne1/Cellule1 …. ColonneN/CelluleN #Partition Offset … Index de colonne * user001 0x0 … premier: xxx dernier: yyy offset: 0x3 … user002 0x153 … premier: xxx dernier: yyy offset: 0x156 … user350 0x5464321 … premier: xxx dernier: yyy offset: 0x5464310 … *-Index.db *-Data.db 31 SStable Partition Key Cache
  • @doanduyhai#C*ModelisationAvancee Format des fichiers Echantillon Offset user001 0x0 user128 0x4500 user256 0x851513 user350 0x5464321 *-Summary.db #p (user001) Longueur ligne Index de colonne * Tombstone Nb de colonnes Colonne1/Cellule1 …. ColonneN/CelluleN #p (user350) Longueur ligne Index de colonne * Tombstone Nb de colonnes Colonne1/Cellule1 …. ColonneN/CelluleN 32 *-Data.dbSStable Key Index Sample
  • @doanduyhai#C*ModelisationAvancee Format des fichiers 1 0 0 1 0 0 1 0 0 0 « foo » h1 h2 h3 33 *-Filter.dbBloom Filter
  • @doanduyhai#C*ModelisationAvancee Format des fichiers 1 0 0 1* 0 0 1 0 1 1 « foo » « bar » h1 h2 h3 34 *-Filter.dbBloom Filter
  • @doanduyhai#C*ModelisationAvancee Format des fichiers 1 0 0 1* 0 0 1 0 1 1 h1 h2 h3 « qux » ? « foo » « bar » 35 *-Filter.dbBloom Filter
  • @doanduyhai#C*ModelisationAvancee Chemin d’écriture Mémoire Disque2 Commit log1 Disque1 . . . 1 Commit log2 Commit logn 36
  • @doanduyhai#C*ModelisationAvancee Chemin d’écriture Mémoire Disque2 Commit log1 Disque1 . . . MemTable Column Family 1 . . . 1 2 Commit log2 Commit logn MemTable Column Family 2 MemTable Column Family n 37
  • @doanduyhai#C*ModelisationAvancee Chemin d’écriture Column Family1 Mémoire Disque2 Commit log1 SStable 1 Disque1 . . . Column Family2 SStable 1 Column Family3 SStable 1 1 3Commit log2 Commit logn 38
  • @doanduyhai#C*ModelisationAvancee Chemin d’écriture Column Family1 Mémoire Disque2 Commit log1 SStable 1 Disque1 . . . Column Family2 SStable 1 Column Family3 SStable 1 1 3Commit log2 Commit logn 39 MemTable Column Family 1 . . . 2 MemTable Column Family 2 MemTable Column Family n
  • @doanduyhai#C*ModelisationAvancee Chemin d’écriture Column Family1 Mémoire Disque2 Commit log1 SStable 1 Disque1 . . . SStable 2 Column Family2 SStable 1 SStable 2 Column Family3 SStable 1 1 3Commit log2 Commit logn 40
  • @doanduyhai#C*ModelisationAvancee Chemin d’écriture Column Family1 Mémoire Disque2 Commit log1 SStable 1 Disque1 . . . SStable 2 SStable 3 Column Family2 SStable 1 SStable 2 SStable 3 SStable 4 SStable 5 Column Family3 SStable 1 1 3 Immutables  Commit log2 Commit logn 41
  • @doanduyhai#C*ModelisationAvancee Chemin de lecture Mémoire Off-Heap Disque Row Cache Mémoire JVM Heap 1 42 SELECT * FROM users WHERE partition =…
  • @doanduyhai#C*ModelisationAvancee Chemin de lecture Mémoire Off-Heap Disque Row Cache Mémoire JVM Heap Bloom Filter 1 2 43 SELECT * FROM users WHERE partition =…
  • @doanduyhai#C*ModelisationAvancee Chemin de lecture Mémoire Off-Heap Disque Row Cache Mémoire JVM Heap Bloom Filter  Partition Key Cache 1 2 3 44 SELECT * FROM users WHERE partition =…
  • @doanduyhai#C*ModelisationAvancee Chemin de lecture Mémoire Off-Heap Disque Row Cache Mémoire JVM Heap Bloom Filter  Partition Key Cache Key Index Sample4 1 2 3 45 SELECT * FROM users WHERE partition =…
  • @doanduyhai#C*ModelisationAvancee Chemin de lecture Mémoire Off-Heap Disque Row Cache Mémoire JVM Heap Bloom Filter  Partition Key Cache Compression offset Key Index Sample4 5 1 2 3 46 SELECT * FROM users WHERE partition =…
  • @doanduyhai#C*ModelisationAvancee Chemin de lecture SStable 1 Mémoire Off-Heap Disque Row Cache Mémoire JVM Heap Bloom Filter  Partition Key Cache Compression offset Key Index Sample4 5 1 Column Family User 2 6 3 47 SELECT * FROM users WHERE partition =…
  • @doanduyhai#C*ModelisationAvancee Chemin de lecture Mémoire Off-Heap Disque Row Cache Mémoire JVM Heap Bloom Filter  Partition Key Cache Compression offset Key Index Sample4 5 Memtable 1 2 7 ∑ 3 SStable 1 Column Family User 6 48 SELECT * FROM users WHERE partition =…
  • @doanduyhai#C*ModelisationAvancee Mémoire Off-Heap Disque Column Family User Row Cache Mémoire JVM Heap Partition Key Cache Commit log1 … Key Index Sample Compression offset Bloom Filter SStable 3 Système de fichiers SStable 2SStable 1 Commit log 2 Commit logn Key Index Sample Compression offset Bloom Filter Key Index Sample Compression offset Bloom Filter 49
  • @doanduyhai#C*ModelisationAvancee Gestion de conflits Données provenant de plusieurs SSTables  merge-sort en mémoire  utilise timestamp → last-write win SStable 1 Pk = xxx Col1,val11,time1 Col2,val21,time1 SStable 2 Pk = xxx Col1,val12,time2 Col3,val31,time3 SStable 3 Pk = xxx Col2,val22,time4 Col4,val41,time4 Pk = xxx Col1, val12,time2 Col2, val22,time4 Col3,val31,time3 Col4,val41,time4 50
  • @doanduyhai#C*ModelisationAvancee Suppression de données SSTables immutables  pas de suppression physique Suppression logique  écrire une colonne tombstone 51
  • @doanduyhai#C*ModelisationAvancee Suppression de données SSTables immutables  pas de suppression physique Suppression logique  écrire une colonne tombstone A la lecture  comparaison timestamp tombstone + timestamp données 52
  • @doanduyhai#C*ModelisationAvancee Compaction Beaucoup de SSTables  beaucoup d’accès disque → lent  fragmentation des données 53
  • @doanduyhai#C*ModelisationAvancee Compaction Beaucoup de SSTables  beaucoup d’accès disque → lent  fragmentation des données Purge des colonnes tombstone 54
  • @doanduyhai#C*ModelisationAvancee Compaction Beaucoup de SSTables  beaucoup d’accès disque → lent  fragmentation des données Purge des colonnes tombstone Type de compaction  SizeTieredCompaction  LeveledCompaction 55
  • @doanduyhai#C*ModelisationAvancee Q & R  
  • @doanduyhai#C*ModelisationAvancee CQL3 EN DÉTAIL CQL3  stockage physique Détails d’implémentation Collections & Maps
  • @doanduyhai#C*ModelisationAvancee Tables simples Schéma CQL3 CREATE TABLE users ( id bigint PRIMARY KEY, nom text, age int); Stockage physique #partition : LongType #colonne: CompositeType(UTF8Type) cellule: ByteType 58
  • @doanduyhai#C*ModelisationAvancee Démo cassandra-cli : « users »
  • @doanduyhai#C*ModelisationAvancee Colonne marqueur RowKey: 10 => (column=, value=, timestamp=…)  => (column=age, value=00000023, timestamp=…) => (column=nom, value=4a6f686e20444f45, timestamp=…) 60
  • @doanduyhai#C*ModelisationAvancee Colonne marqueur INSERT INTO USERS(id) VALUES(12) RowKey: 10 => (column=, value=, timestamp=…)  => (column=age, value=00000023, timestamp=…) => (column=nom, value=4a6f686e20444f45, timestamp=…) RowKey: 10 => (column=, value=, timestamp=…) 61
  • @doanduyhai#C*ModelisationAvancee Tables « clustered » (agrégées) Schéma CQL3 62 CREATE TABLE commentaires ( article_id int, date_creation timestamp, auteur text, contenu text, PRIMARY KEY (article_id, date_creation));
  • @doanduyhai#C*ModelisationAvancee Tables « clustered » (agrégées) CREATE TABLE commentaires ( article_id int, date_creation timestamp, auteur text, contenu text, PRIMARY KEY (article_id, date_creation)); #partition (1er) #col d’agrégation/clustering (2ème … ) Schéma CQL3 63
  • @doanduyhai#C*ModelisationAvancee Tables « clustered » (agrégées) Stockage physique #partition : IntType #colonne: CompositeType(DateType,UTF8Type) cellule: ByteType Map<article_id, SortedMap<date_creation, SortedMap<nom_colonne,cellule>>> 64
  • @doanduyhai#C*ModelisationAvancee Tables « clustered » (agrégées) #partition : IntType #colonne: CompositeType(DateType,UTF8Type) cellule: ByteType CREATE TABLE commentaires ( article_id int, date_creation timestamp, auteur text, contenu text, PRIMARY KEY (article_id, date_creation)); Map<article_id, SortedMap<date_creation, SortedMap<nom_colonne,cellule>>> 65
  • @doanduyhai#C*ModelisationAvancee Tables « clustered » (agrégées) article_id | date_creation | auteur | contenu ----------------+-----------------------------------+--------------------+-------------------------------- 1 | 2014-04-16 10:00:00| Dupond| Cet article est génial 1 | 2014-04-16 10:01:00| Martin| Très bon article CREATE TABLE commentaires ( article_id int, date_creation timestamp, auteur text, contenu text, PRIMARY KEY (article_id, date_creation)); Map<article_id, SortedMap<date_creation, SortedMap<nom_colonne,cellule>>> 66
  • @doanduyhai#C*ModelisationAvancee Tables « clustered » (agrégées) RowKey: 1 => (column=2014-04-16 10:00:00+0100:, value=,…) => (column=2014-04-16 10:00:00+0100:auteur, value=‘Dupond’, …) => (column=2014-04-16 10:00:00+0100:contenu, value=‘Cet article est génial’,…) => (column=2014-04-16 10:01:00+0100:, value=,…) => (column=2014-04-16 10:01:00+0100:auteur, value=‘Martin’, …) => (column=2014-04-16 10:01:00+0100:contenu, value=‘Très bon article’,…) CREATE TABLE commentaires ( article_id int, date_creation timestamp, auteur text, contenu text, PRIMARY KEY (article_id, date_creation)); Map<article_id, SortedMap<date_creation, SortedMap<nom_colonne,cellule>>> 67
  • @doanduyhai#C*ModelisationAvancee Tables « clustered » (agrégées) #partition : UTF8Type #colonne: CompositeType(UTF8Type,IntType,UTF8Type) cellule: ByteType Map<operateur, SortedMap<ville, SortedMap<date, SortedMap<nom_colonne,cellule>>>> CREATE TABLE qualite_reseau ( operateur text, ville text, date int, // format YYYYmmDDhh qualite double, PRIMARY KEY (operateur,ville,date)); 68
  • @doanduyhai#C*ModelisationAvancee Tables « clustered » (agrégées) operateur | ville | date | qualité ----------------+----------+---------------------+------ Orange | Lyon | 2014041612 | 0.93 Orange | Paris | 2014041612 | 0.89 Orange | Paris | 2014041613 | 0.91 SFR | Lyon | 2014041612 | 0.88 SFR | Paris | 2014041612 | 0.78 SFR | Paris | 2014041615 | 0.93 CREATE TABLE qualite_reseau ( operateur text, ville text, date int, // format YYYYmmDDhh qualite double, PRIMARY KEY (operateur,ville,date)); Map<operateur, SortedMap<ville, SortedMap<date, SortedMap<nom_colonne,cellule>>>> 69
  • @doanduyhai#C*ModelisationAvancee Tables « clustered » (agrégées) CREATE TABLE qualite_reseau ( operateur text, ville text, date int, // format YYYYmmDDhh qualite double, PRIMARY KEY (operateur,ville,date)); RowKey: Orange => (column=Lyon:2014041612:qualite, value=0.93, timestamp=…) => (column=Paris:2014041612:qualite, value=0.89, timestamp=…) => (column=Paris:2014041613:qualite, value=0.91, timestamp=…) ------------------- RowKey: SFR => (column=Lyon:2014041612:qualite, value=0.88, timestamp=…) => (column=Paris:2014041612:qualite, value=0.78, timestamp=…) => (column=Paris:2014041615:qualite, value=0.93, timestamp=…) Map<operateur, SortedMap<ville, SortedMap<date, SortedMap<nom_colonne,cellule>>>> 70
  • @doanduyhai#C*ModelisationAvancee Q & R  
  • @doanduyhai#C*ModelisationAvancee Pourquoi CQL3 ? Retour du schéma (schemaless) 72
  • @doanduyhai#C*ModelisationAvancee Pourquoi CQL3 ? Retour du schéma (schemaless) Découpler vue logique/stockage physique 73
  • @doanduyhai#C*ModelisationAvancee Pourquoi CQL3 ? Retour du schéma (schemaless) Découpler vue logique/stockage physique API/requête plus familière & facile à prendre en main 74
  • @doanduyhai#C*ModelisationAvancee Pourquoi CQL3 ? Retour du schéma (schemaless) Découpler vue logique/stockage physique API/requête plus familière & facile à prendre en main Pensez aux ops !!!! 75
  • @doanduyhai#C*ModelisationAvancee La clause « WHERE » S’applique aux clés des SortedMap (unicité) 76
  • @doanduyhai#C*ModelisationAvancee La clause « WHERE » S’applique aux clés des SortedMap (unicité) Autorise des recherches par plage (tri) 77
  • @doanduyhai#C*ModelisationAvancee La clause « WHERE » S’applique aux clés des SortedMap (unicité) Autorise des recherches par plage (tri) Ordre des clés très important!!!!  SELECT * FROM qualite_reseau WHERE operateur = ‘ORANGE’ AND ville = ‘Paris’ AND date ≥ 2014041619 AND date ≤ 2014041621  SELECT * FROM qualite_reseau WHERE operateur = ‘ORANGE’ AND date ≥ 2014041619 AND date ≤ 2014041621 78
  • @doanduyhai#C*ModelisationAvancee Les méta-données de CQL3 Noms des colonnes « clustered » dans les tables ? key_aliases | key_validator | column_aliases | comparator --------------------+----------------------+--------------------------+------------------------------------------------------------------------------- ["operateur"] | UTF8Type | ["ville","date"] | CompositeType(UTF8Type,Int32Type,UTF8Type) SELECT key_aliases,key_validator,column_aliases,comparator FROM system.schema_columnfamilies WHERE keyspace_name=‘xxx' AND columnfamily_name=‘qualite_reseau’ 79
  • @doanduyhai#C*ModelisationAvancee Détails d’implémentation Pourquoi ne pas tout stocker dans les #colonnes ? 80
  • @doanduyhai#C*ModelisationAvancee Détails d’implémentation Pourquoi ne pas tout stocker dans les #colonnes ? RowKey: SFR => (column=Lyon:2013110512:qualite, value=0.88) RowKey: SFR => (column=Lyon:2013110512:qualite:0.88, value=) 81
  • @doanduyhai#C*ModelisationAvancee Détails d’implémentation Pourquoi ne pas tout stocker dans les #colonnes ?  limite des 64K pour les #colonnes  colonnes counter, type spécial RowKey: SFR => (column=Lyon:2013110512:qualite, value=0.88) RowKey: SFR => (column=Lyon:2013110512:qualite:0.88, value=) 82
  • @doanduyhai#C*ModelisationAvancee Détails d’implémentation Pourquoi ne pas tout stocker dans les #colonnes ?  limite des 64K pour les #colonnes  colonnes counter, type spécial → counter colonne d’agrégation RowKey: SFR => (column=Lyon:2013110512:qualite, value=0.88) RowKey: SFR => (column=Lyon:2013110512:qualite:0.88, value=) 83
  • @doanduyhai#C*ModelisationAvancee Détails d’implémentation Eager fetching par slice query CREATE TABLE fichiers ( user_id bigint, file_id timeuuid, nom text, payload blob, taille int, PRIMARY KEY(user_id, file_id)); 84
  • @doanduyhai#C*ModelisationAvancee Détails d’implémentation Eager fetching par slice query 85 SELECT nom, taille FROM file WHERE user_id = 10 ORDER BY file_id DESC;
  • @doanduyhai#C*ModelisationAvancee Détails d’implémentation Eager fetching par slice query 10 uuid1: uuid1:nom uuid1:payload uuid1:taille uuid2: … Ø video.mp4 xxxxxxxxxxxx 9Mb Ø 86 SELECT nom, taille FROM file WHERE user_id = 10 ORDER BY file_id DESC;
  • @doanduyhai#C*ModelisationAvancee Collection & Map CREATE TABLE collections_maps ( id int PRIMARY KEY, amis list<text>, suiveurs set<text>, adresse map<text,text>) ; INSERT INTO collections_maps(id,amis,suiveurs, adresse) VALUES(10,[‘Dupond’,’Martin’],{‘Jean’,’Jacques’},{‘pays’:’FR’,’ville’:’Paris’}); 87
  • @doanduyhai#C*ModelisationAvancee Collection & Map RowKey: 10 => (column=, value=, timestamp=…) => (column=amis:’uuid1’, value=‘Dupond’, timestamp=…) => (column=amis:’uuid2’, value=‘Martin’, timestamp=…) => (column=adresse:’pays’, value=‘FR’, timestamp=…) => (column=adresse:’ville’, value=‘Paris’, timestamp=…) => (column=suiveurs:’Jean’, value=, timestamp=…) => (column=suiveurs:’Jacques’, value=, timestamp=…) 88
  • @doanduyhai#C*ModelisationAvancee Collection & Map Liste: => (column=amis:’uuid1’, value=‘Dupond’, timestamp=…) => (column=amis:’uuid2’, value=‘Martin’, timestamp=…) SortedMap<nom_de_colonne,SortedMap<uuid, valeur>> Ordre 89
  • @doanduyhai#C*ModelisationAvancee Collection & Map Set: => (column=suiveurs:’Jean’, value=, timestamp=…) => (column=suiveurs:’Jacques’, value=, timestamp=…) SortedMap<nom_de_colonne,SortedMap<valeur,Ø>> Unicité 90
  • @doanduyhai#C*ModelisationAvancee Collection & Map Map: => (column=adresse:’pays’, value=‘FR’, timestamp=…) => (column=adresse:’ville’, value=‘Paris’, timestamp=…) SortedMap<nom_de_colonne,SortedMap<clé,valeur>> 91
  • @doanduyhai#C*ModelisationAvancee Collection & Map Set & Map  insertion et suppression d’élément(s) 92 UPDATE xxx SET suiveurs = suiveurs + {‘Pierre’} UPDATE xxx SET adresse = adresse + {‘rue’ : ’rue de la paix’} UPDATE xxx SET adresse[‘ville’] = ’Lyon’
  • @doanduyhai#C*ModelisationAvancee Collection & Map Liste  ajout d’élément(s) en tête/en queue 93 UPDATE xxx SET amis = amis + [‘Pierre’] UPDATE xxx SET amis = [‘Pierre’] + amis
  • @doanduyhai#C*ModelisationAvancee Collection & Map Liste  ajout d’élément(s) en tête/en queue  modification/suppression d’élément à l’index i  insertion d’élément à l’index i 94 UPDATE xxx SET amis = amis + [‘Pierre’] UPDATE xxx SET amis = [‘Pierre’] + amis UPDATE xxx SET amis[1] = ‘Paul’ UPDATE xxx SET amis[1] = null
  • @doanduyhai#C*ModelisationAvancee Collection & Map 1262304000000 01/01/2012 1383084226280 Append1REFERENCE TIME Liste prepend/append 95
  • @doanduyhai#C*ModelisationAvancee Collection & Map 1262304000000 01/01/2012 1383084226280 Prepend2 -xxxxxxx Append1 now() REFERENCE TIME 96 Liste prepend/append
  • @doanduyhai#C*ModelisationAvancee Collection & Map 1262304000000 01/01/2012 1383084226280 Append3Prepend2 -xxxxxxx Append1 now() REFERENCE TIME 97 Liste prepend/append
  • @doanduyhai#C*ModelisationAvancee Chargement  complet  taille recommandée ≈ [100-1000] Collection & Map 98
  • @doanduyhai#C*ModelisationAvancee Chargement  complet  taille recommandée ≈ [100-1000] Index secondaire possible (C* 2.1) Requête avec ‘CONTAINS’ (C* 2.1)  SELECT … FROM collections_maps WHERE amis CONTAINS ‘Marc’ Collection & Map 99
  • @doanduyhai#C*ModelisationAvancee Q & R  
  • @doanduyhai#C*ModelisationAvancee TECHNIQUES DE MODÉLISATION DE BASE De SQL vers Cassandra Dé-normalisation et compromis Gérer la mutabilité Pièges & bonnes pratiques
  • @doanduyhai#C*ModelisationAvancee 1-1, n-1  normalisé De SQL à Cassandra CREATE TABLE commentaires ( article_id uuid, date_creation timestamp, auteur_id uuid, contenu text, PRIMARY KEY(article_id, date_creation)); Personne 1 écrit N Commentaire 102
  • @doanduyhai#C*ModelisationAvancee 1-1, n-1  dé-normalisé De SQL à Cassandra CREATE TABLE commentaires ( article_id uuid, date_creation timestamp, auteur_data text, //JSON ? contenu text, PRIMARY KEY(article_id, date_creation)); 1 écrit N Commentaire Personne 103
  • @doanduyhai#C*ModelisationAvancee 1-n, n-n  normalisé De SQL à Cassandra CREATE TABLE amis ( user_id uuid, ami_id uuid, PRIMARY KEY(user_id, ami_id)) ; Personne N est ami avec N 104
  • @doanduyhai#C*ModelisationAvancee 1-n, n-n  dé-normalisé De SQL à Cassandra CREATE TABLE amis ( user_id uuid, ami_id uuid, ami_data text, // JSON ? PRIMARY KEY(user_id, ami_id)) ; Personne N est ami avec N 105
  • @doanduyhai#C*ModelisationAvancee 1-1, n-1  compact  avantages/inconvénients Type de dé-normalisation CREATE TABLE commentaires ( article_id uuid, date_creation timestamp, auteur_data text, //JSON ? contenu text, PRIMARY KEY(article_id, date_creation)); 106
  • @doanduyhai#C*ModelisationAvancee 1-1, n-1  éclaté  avantages/inconvénients Type de dé-normalisation CREATE TABLE commentaires ( article_id uuid, date_creation timestamp, auteur_id uuid, auteur_nom text, auteur_bio text, … contenu text, PRIMARY KEY(article_id, date_creation)); 107
  • @doanduyhai#C*ModelisationAvancee n-1, n-n  compact avec collections & maps  égalité code vs égalité C* !!! Type de dé-normalisation CREATE TABLE amis ( user_id uuid, amis set<text>, // JSON ? PRIMARY KEY(user_id)) ; 108
  • @doanduyhai#C*ModelisationAvancee n-1, n-n  éclaté avec table « clustered » Type de dé-normalisation CREATE TABLE amis ( user_id uuid, ami_id uuid, ami_nom text, ami_bio text, … PRIMARY KEY(user_id, ami_id)) ; 109
  • @doanduyhai#C*ModelisationAvancee Gérer la mutabilité 110
  • @doanduyhai#C*ModelisationAvancee L’éliminer Gérer la mutabilité CREATE TABLE commentaires ( article_id uuid, date_creation timestamp, auteur_id uuid, auteur_login text, auteur_bio text, auteur_localisation text, … contenu text, PRIMARY KEY(article_id, date_creation)); 111
  • @doanduyhai#C*ModelisationAvancee Approche CQRS* Gérer la mutabilité CREATE TABLE amis ( user_id uuid, ami_id uuid, ami_nom text, ami_bio text, … PRIMARY KEY(user_id, ami_id)) ; 112 * Command Query Responsability Segregation
  • @doanduyhai#C*ModelisationAvancee Approche CQRS* Gérer la mutabilité CREATE TABLE amis ( user_id uuid, ami_id uuid, ami_nom text, ami_bio text, … PRIMARY KEY(user_id, ami_id)) ; Process M.A.J de la bio des users 113 * Command Query Responsability Segregation
  • @doanduyhai#C*ModelisationAvancee Les pièges de la dé-normalisation Ne pas assez dé-normaliser  problème du N+1 select/read-before-write 100 commentaires → 101 selects CREATE TABLE commentaires ( article_id uuid, date_creation timestamp, auteur_id uuid, contenu text, PRIMARY KEY(article_id, date_creation)); 114
  • @doanduyhai#C*ModelisationAvancee Les pièges de la dé-normalisation Compromis fonctionnels !  pagination par 10 commentaires  max 11 selects CREATE TABLE commentaires ( article_id uuid, date_creation timestamp, auteur_id uuid, contenu text, PRIMARY KEY(article_id, date_creation)); 115
  • @doanduyhai#C*ModelisationAvancee Les pièges de la dé-normalisation Trop dé-normaliser  intégrité des données  mises à jour complexes  batchs de correction de données …. cauchemardesques 116
  • @doanduyhai#C*ModelisationAvancee Les pièges de la dé-normalisation Se couvrir fonctionnellement !!!  BDD, test d’acceptance  tests unitaires 117
  • @doanduyhai#C*ModelisationAvancee Les pièges de la dé-normalisation Given 2 users Foo and Bar When Foo adds Bar as friend Then Foo friends list should display Bar’s details Given 2 users Foo and Bar When Foo adds Bar as friend And Bar changes his bio Then Foo should see new Bar’s bio in his friends list Given 2 users Foo and Bar When Foo adds Bar as friend And Bar deletes his account Then Foo should not see Bar in his friend list 118
  • @doanduyhai#C*ModelisationAvancee TODO  approche query-first Bonnes pratiques 119
  • @doanduyhai#C*ModelisationAvancee TODO  approche query-first  TDD & BDD  compromis fonctionnels  CQRS Bonnes pratiques 120
  • @doanduyhai#C*ModelisationAvancee Q & R  
  • @doanduyhai#C*ModelisationAvancee
  • @doanduyhai#C*ModelisationAvancee TECHNIQUES DE MODÉLISATION AVANCÉE Types de clés Ordre d’agrégation La clause IN Wide row et « bucketing » Le type counter
  • @doanduyhai#C*ModelisationAvancee Clés de partition Clé de partition simple CREATE TABLE xxx ( partition uuid, clustering1 uuid, clustering2 uuid, …., PRIMARY KEY(partition, clustering1,clustering2)); 124
  • @doanduyhai#C*ModelisationAvancee Clés de partition Clé de partition « composite » CREATE TABLE xxx ( partition1 uuid, partition2 text, clustering1 uuid, clustering2 uuid, …., PRIMARY KEY((partition1, partition2), clustering1, clustering2)); #partition: CompositeType(UUIDType,UTF8Type) #colonne: CompositeType(UUIDType,UUIDType) cellule: ByteType 125
  • @doanduyhai#C*ModelisationAvancee Clés de partition Clé de partition « composite » CREATE TABLE xxx ( partition1 uuid, partition2 text, clustering1 uuid, clustering2 uuid, …., PRIMARY KEY((partition1, partition2), clustering1, clustering2)); 126
  • @doanduyhai#C*ModelisationAvancee Clés d’agrégation Pseudo « GROUP BY » Map<partition, SortedMap<clustering1, SortedMap<clustering2,cellule>>> PRIMARY KEY(partition, clustering1,clustering2); 127
  • @doanduyhai#C*ModelisationAvancee Clés d’agrégation Unicité par tuple 128 CREATE TABLE notes_film ( film_id uuid, note uuid, user_id int, commentaire text, PRIMARY KEY(film_id, note));
  • @doanduyhai#C*ModelisationAvancee Clés d’agrégation Unicité par tuple 129 CREATE TABLE notes_film ( film_id uuid, note uuid, user_id int, commentaire text, PRIMARY KEY(film_id, note)); 1 note/film
  • @doanduyhai#C*ModelisationAvancee CREATE TABLE notes_film ( film_id uuid, note uuid, user_id int, commentaire text, PRIMARY KEY(film_id, note, user_id)); Clés d’agrégation Unicité par tuple CREATE TABLE notes_film ( film_id uuid, note uuid, user_id int, commentaire text, PRIMARY KEY(film_id, note)); 1 note/film 1 note/user 130
  • @doanduyhai#C*ModelisationAvancee Ordre d’agrégation Tri descendant naturel CREATE TABLE timeline ( user_id uuid, tweet_id timeuuid, tweet text, PRIMARY KEY (user_id, tweet_id)) WITH CLUSTERING ORDER (tweet_id DESC); 131
  • @doanduyhai#C*ModelisationAvancee Ordre d’agrégation Tri descendant naturel  peu efficace, raison ? → scan en arrière 10 uuid1uuid2 … uuid98 uuid99 uuid100 … … … … … … 33 uuid1 uuid2 … uuid51 uuid52 … … … … … … … … 132
  • @doanduyhai#C*ModelisationAvancee 133 Sur clé de partition « composite » CREATE TABLE xxx ( partition1 uuid, partition2 text, …. PRIMARY KEY((partition1, partition2)); SELECT * FROM xxx WHERE partition1 = #p1 AND partition2 IN (#p21, #p22, …) La clause « IN » SELECT * FROM xxx WHERE partition1 IN (#p11, #p12, …) AND partition2 = #p2
  • @doanduyhai#C*ModelisationAvancee 134 Sur clé d’agrégation CREATE TABLE xxx (partition uuid, clustering1 uuid, clustering2 uuid, clustering3 uuid …., PRIMARY KEY(partition, clustering1, clustering2, clustering3)); La clause « IN » SELECT … WHERE clustering1 = #c1 AND clustering2 IN (#c21, #c22, …) SELECT … WHERE clustering1 = #c1 AND clustering2 = #c2 AND clustering3 IN (#c31, #c32, …) SELECT … WHERE clustering1 = #c1 AND clustering2 IN (#c21, #c22, …) AND clustering3 = #c3
  • @doanduyhai#C*ModelisationAvancee 135 Comment ça marche ? → multiget ! La clause « IN »
  • @doanduyhai#C*ModelisationAvancee 136 Comment ça marche ? → multiget ! Combinaison linéaire  (#p1, #p21) && (#p1, #p22) La clause « IN » SELECT * FROM xxx WHERE partition1 = #p1 AND partition2 IN (#p21, #p22, …)
  • @doanduyhai#C*ModelisationAvancee Wide rows et « bucketing » Lignes trop larges  limite physique 2.109  hot-spots si nb #partition « nb #col  réparation coûteuse → 1colonne diffère, toute la ligne réparée 137
  • @doanduyhai#C*ModelisationAvancee Wide rows et « bucketing » Bucketing  découper une ligne physique sur plusieurs partitions  répartit la charge  attention aux requêtes! 138
  • @doanduyhai#C*ModelisationAvancee Démo cqlsh: « metrics_annee », « metrics_mois »
  • @doanduyhai#C*ModelisationAvancee Wide rows et « bucketing » Requêtes inter-partition  toutes les métriques CPU entre 25 Janvier et 10 Février ? CREATE TABLE metrics_mois ( type text, mois int, date timestamp, valeur double, PRIMARY KEY ((type, mois), date)) ; 140
  • @doanduyhai#C*ModelisationAvancee Wide rows et « bucketing » Requêtes inter-partition  toutes les métriques CPU entre 25 Janvier et 10 Février ? CREATE TABLE metrics_mois ( type text, mois int, date timestamp, valeur double, PRIMARY KEY ((type, mois), date)) ; SELECT * FROM metrics_mois WHERE type = ‘CPU’ AND mois IN (201401, 201402) AND date>=‘2014-01-25 00:00:00+0100’ AND date<=‘2014-02-10 00:00:00+0100’; 141
  • @doanduyhai#C*ModelisationAvancee Wide rows et « bucketing » Implémentation par multiget SELECT * FROM metrics_mois WHERE type = ‘CPU’ AND mois = 201401 AND date>=‘2014-01-25 00:00:00+0100’ AND date<=‘2014-02-10 00:00:00+0100’ && SELECT * FROM metrics_mois WHERE type = ‘CPU’ AND mois = 201402 AND date>=‘2014-01-25 00:00:00+0100’ AND date<=‘2014-02-10 00:00:00+0100’ 142
  • @doanduyhai#C*ModelisationAvancee 2014-02-01 00:00:00 … 2014-02-10 23:59:59 … 0.24 … 0.23 … Wide rows et « bucketing » Requêtes inter-partition CPU:201401 2014-01-01 00:00:00 2014-01-01 00:00:10 … 2014-01-25 00:00:00 … 2014-01-31 23:59:59 0.24 0.23 … 0.27 … 0.25 25 Jan. – 31Jan. 01 Fev. – 10 Fev. 143 CPU:201402
  • @doanduyhai#C*ModelisationAvancee Wide rows et « bucketing » Pré-requis  valeur de #col de croissance monotone entre les partitions  date/timeuuid bons candidats 144
  • @doanduyhai#C*ModelisationAvancee Wide rows et « bucketing » Contre-exemple CPU:2013 01 02 03 04 05 06 07 08 09 10 11 12 0.75 0.71 0.68 0.79 0.69 0.73 0.75 0.77 0.83 0.78 0.79 0.88 CPU:2014 01 02 03 04 05 06 07 08 09 10 11 12 0.71 0.72 0.67 0.80 0.71 0.75 0.74 0.76 0.81 0.79 0.83 0.87 SELECT moyenne FROM metrics_annee WHERE type = ‘CPU’ AND annee IN (2013, 2014) AND mois ≥ 11AND mois ≤ 02; 145
  • @doanduyhai#C*ModelisationAvancee Q & R  
  • @doanduyhai#C*ModelisationAvancee Le type counter Fonctionnement  seulement incrément/décrément  suppression possible  ne jamais réutiliser un compteur supprimé Limitations  non idempotent  pas 100% précis (ok pour analytics) 147
  • @doanduyhai#C*ModelisationAvancee Les patterns avec counter / vote  naïve: incr/decr 1 seul compteur  version duale: pour/contre  infos étendues total: pour + contre ratio: pour/(pour + contre) CREATE TABLE popularite ( article_id uuid PRIMARY KEY pour counter, contre counter) ; 148
  • @doanduyhai#C*ModelisationAvancee Les patterns avec counter Système de rating CREATE TABLE film_rating ( film_id uuid PRIMARY KEY une_etoile counter, deux_etoiles counter, trois_etoiles counter, quatre_etoiles counter, cinq_etoiles counter) ; 149
  • @doanduyhai#C*ModelisationAvancee Démo cqlsh : « abonnes_telecom », « abonnes_telecom_par_localite »
  • @doanduyhai#C*ModelisationAvancee Q & R  
  • @doanduyhai#C*ModelisationAvancee TECHNIQUES DE MODÉLISATION EXOTIQUES Time To Live FTW Timestamp, WTF ? C.A.S. distribué
  • @doanduyhai#C*ModelisationAvancee Time To Live En bref  données volatiles/temporaires  seulement sur colonnes  résolution en seconde  expiré côté serveur 153
  • @doanduyhai#C*ModelisationAvancee Time To Live Jetons de sécurité CREATE TABLE oauth_tokens( token uuid PRIMARY KEY, user_id int, permissions set<text>) ; 154
  • @doanduyhai#C*ModelisationAvancee Time To Live Jetons de sécurité Jetons à usage unique CREATE TABLE oauth_tokens( token uuid PRIMARY KEY, user_id int, permissions set<text>) ; CREATE TABLE code_de_validation( code_de_validation text PRIMARY KEY, email text) ; 155
  • @doanduyhai#C*ModelisationAvancee Time To Live Fonction ttl() dans CQL3 156 SELECT ttl(code_de_validation) FROM code_de_validation WHERE code_de_validation=‘sdfkl0rf’;
  • @doanduyhai#C*ModelisationAvancee Time To Live Rate limiting CREATE TABLE rate_limiting ( user_id int, tentative uuid, PRIMARY KEY (user_id, tentative)) ; 157
  • @doanduyhai#C*ModelisationAvancee Time To Live Rate limiting CREATE TABLE rate_limiting ( user_id int, tentative uuid, PRIMARY KEY (user_id, tentative)) ; SELECT COUNT(*) FROM rate_limiting WHERE user_id =10 158
  • @doanduyhai#C*ModelisationAvancee Démo Rate Limiting Source: bit.ly/1noCqY1
  • @doanduyhai#C*ModelisationAvancee Timestamp En bref  automatique sur chaque colonne insérée  valeur modifiable par client  résolution en micro-seconde  utilisé pour résolution de conflit 160
  • @doanduyhai#C*ModelisationAvancee Démo Timestamp Barrière d’écriture Source: bit.ly/1noCqY1
  • @doanduyhai#C*ModelisationAvancee C.A.S. distribué Lightweight transaction  depuis C* 2.0  implémentation de Paxos  très coûteux (3 aller/retours) !  utile pour 1% use-cases 162
  • @doanduyhai#C*ModelisationAvancee C.A.S. distribué Contrainte d’intégrité UPDATE abonnes SET preferences=… WHERE identifiant=… IF compte_valide=true 163
  • @doanduyhai#C*ModelisationAvancee C.A.S. distribué Contrainte d’intégrité Contrainte d’unicité UPDATE abonnes SET preferences=… WHERE identifiant=… IF compte_valide=true INSERT INTO abonnes(…) VALUES(…) IF NOT EXISTS 164
  • @doanduyhai#C*ModelisationAvancee Démo cqlsh : « lock »
  • @doanduyhai#C*ModelisationAvancee Q & R  
  • @doanduyhai#C*ModelisationAvancee LES ANTI-PATTERNS Queues et suppression Détection de présence/d’absence Read-before-write Row cache
  • @doanduyhai#C*ModelisationAvancee Queues Implémentation naïve a b c d e Queue FIFO C* a b c d e 168
  • @doanduyhai#C*ModelisationAvancee Queues Implémentation naïve a b c d e b c d e Queue FIFO C* a b c d e a b c d e a 169
  • @doanduyhai#C*ModelisationAvancee Queues Implémentation naïve a b c d e Queue FIFO C* a b c d e a b c d e a b c d e f a b c d e a f 170 b c d e
  • @doanduyhai#C*ModelisationAvancee Queues Implémentation naïve a b c d e Queue FIFO C* a b c d e a b c d e a b c d e f a b c d e a f c d e f a b c d e a f b 171 b c d e
  • @doanduyhai#C*ModelisationAvancee Queues Queue FIFO consommée a b c d e a f b c d e f 172
  • @doanduyhai#C*ModelisationAvancee Queues Queue FIFO consommée Queue avec rollback a b c d e a f b c d e f a a a a a a a a a a … a 173
  • @doanduyhai#C*ModelisationAvancee Queues Queue FIFO consommée Queue avec rollback Limite 100K tombstones → leveled compaction ≈ Partition trop large! a b c d e a f b c d e f a a a a a a a a a a … a 174
  • @doanduyhai#C*ModelisationAvancee Queues: solutions Utiliser JMS  best tool for the job !!!! 175
  • @doanduyhai#C*ModelisationAvancee Queues: solutions Utiliser JMS  best tool for the job !!!! Besoin de distribution ?  Apache Kafka 176
  • @doanduyhai#C*ModelisationAvancee Queues: solutions Bucketing & croissance monotone  10 000 éléments/bucket #p:#bucket1 #t1 #t2 #t3 … #t10000 m1 m2 m3 … m10000 #p:#bucket2 #t100001 #t10002 #t10003 … #t20000 m100001 m10002 m10003 … m20000 #p:#bucket3 #t200001 #t20002 #t20003 … #t30000 m200001 m20002 m20003 … m30000 177
  • @doanduyhai#C*ModelisationAvancee Queues: accès concurrents Multiple sources sn  ordonner les sources: s1, s2 … sn 178
  • @doanduyhai#C*ModelisationAvancee Queues: accès concurrents Multiple sources sn  ordonner les sources: s1, s2 … sn  round-robin sur les #bucket, pour sm : #bucket%n = m%n 179
  • @doanduyhai#C*ModelisationAvancee Queues: accès concurrents Multiple sources sn  ordonner les sources: s1, s2 … sn  round-robin sur les #bucket, pour sm : #bucket%n = m%n  bucket suivant si #élément = 10 000 180
  • @doanduyhai#C*ModelisationAvancee Queues: accès concurrents Exemple n = 3  s1 #bucket = {1, 4, 7…}, s2 #bucket = {2, 5, 8…}, s3 #bucket = {3, 6, 9…} 181 #p:#bucket1 … … … … … … … … … … #p:#bucket2 … … … … … … … … … … #p:#bucket3 … … … … … … … … … … #p:#bucket4 … … … … … … … … … … #p:#bucket5 … … … … … … … … … … s1 s1 s2 s2 s3
  • @doanduyhai#C*ModelisationAvancee Queues: accès concurrents Multiple consommateurs cn  idem 182
  • @doanduyhai#C*ModelisationAvancee Queues: accès concurrents Rollback  pas de suppression !!! cm remet messages dans #bucketm+? futur → comptage faussé pour cm+? 183
  • @doanduyhai#C*ModelisationAvancee Queues: accès concurrents Rollback  pas de suppression !!! cm remet messages dans #bucketm+? futur → comptage faussé pour cm+? 184 #p:#bucketm … … … … … … … … … … #p:#bucketm+1 … … … … … … … … … … #p:#bucketm+2 … … … … … … … … … … … … … … … … #p:#bucketm+3 … … … … … … … … … …
  • @doanduyhai#C*ModelisationAvancee Queues: accès concurrents Solution rollback  compteur d’éléments supplémentaires pour messages rollbackés  complexité technique 185 #p:#bucketm … … … … … … … … … … #p:#bucketm+1 … … … … … … … … … … #p:#bucketm+2 … … … … … … … … … … … … … … … … #p:#bucketm+3 … … … … … … … … … … +3
  • @doanduyhai#C*ModelisationAvancee Détection de présence/d’absence 186
  • @doanduyhai#C*ModelisationAvancee Détection de présence/d’absence Jetons de sécurité Vérification CREATE TABLE user_tokens ( user_id int, token uuid, PRIMARY KEY(user_id, token)) ; SELECT count(*) FROM user_tokens WHERE user_id =… AND token =… 187
  • @doanduyhai#C*ModelisationAvancee Détection de présence/d’absence Chemin de lecture  Bloom filter en mémoire  partition key cache en mémoire  accès disque SSTable 188
  • @doanduyhai#C*ModelisationAvancee Mémoire Off-Heap Disque Row Cache Mémoire JVM Heap Bloom Filter  Partition Key Cache Compression offset Key Index Sample4 5 Memtable 1 2 7 ∑ 3 SStable 1 Column Family User 6 Détection de présence/d’absence SELECT count(*) FROM user_tokens WHERE user_id =… AND token =… 189
  • @doanduyhai#C*ModelisationAvancee Détection de présence/d’absence Nouvelle modélisation Nouveau chemin de lecture  Bloom filter en mémoire  partition key cache en mémoire  accès disque SSTable en cas de faux positif CREATE TABLE user_token ( user_id int, token uuid, PRIMARY KEY((user_id, token))) ; 190
  • @doanduyhai#C*ModelisationAvancee Mémoire Off-Heap Disque Row Cache Mémoire JVM Heap Bloom Filter  Partition Key Cache Memtable 1 2 4 ∑ 3 Détection de présence/d’absence SELECT count(*) FROM user_tokens WHERE user_id =… AND token =… 191
  • @doanduyhai#C*ModelisationAvancee Row cache Use-cases  données référentielles  taille raisonnable  partitions accédées très fréquemment 192
  • @doanduyhai#C*ModelisationAvancee Row cache Use-cases  données référentielles  taille raisonnable  partitions accédées très fréquemment Important  monitoring nécessaire du hit rate & de la taille des données !!!  coût de la sérialisation/dé-sérialisation (off-heap) 193
  • @doanduyhai#C*ModelisationAvancee Q & R  
  • @doanduyhai#C*ModelisationAvancee LES INDEX SECONDAIRES Implémentation Use-cases recommandés Retour d’expérience
  • @doanduyhai#C*ModelisationAvancee Implémentation Naïve CREATE TABLE user_par_pays ( pays text, user_id int, PRIMARY KEY(pays, user_id)) ; 196
  • @doanduyhai#C*ModelisationAvancee Implémentation Naïve Problèmes  197 partitions max → wide rows  distribution pays non uniforme → hot-spots  m.a.j. non atomique  bucketing non adapté CREATE TABLE user_par_pays ( pays text, user_id int, PRIMARY KEY(pays, user_id)) ; 197
  • @doanduyhai#C*ModelisationAvancee 11:Martin, 85:Sophie, 57:Smith Implémentation Distribuée  10, Dupond, FR  11, Martin, FR  85, Sophie, FR  25, John, US  74, Helen, US  57, Smith, UK  18, Heinrich, DE n4 n3 n2 10:Dupond, 25:John, 18:Heinrich n1 74:Helen FR → {10} US → {25} DE → {18} FR → {11,85} UK → {57} US → {74} 198
  • @doanduyhai#C*ModelisationAvancee 11:Martin, 85:Sophie, 57:Smith Implémentation Conséquences bénéfiques  meilleure distribution, hot-spots  même distribution que données n4 n3 n2 n1 10:Dupond, 25:John, 18:Heinrich 74:Helen FR → {10} US → {25} DE → {18} FR → {11,85} UK → {57} US → {74} 199
  • @doanduyhai#C*ModelisationAvancee 11:Martin, 85:Sophie, 57:Smith Implémentation Conséquences fâcheuses  lecture index → scan de N/R nœuds !!!  N = #nœuds  R = replication factor n4 n3 n2 n1 10:Dupond, 25:John, 18:Heinrich 74:Helen FR → {10} US → {25} DE → {18} FR → {11,85} UK → {57} US → {74} 200 N = 4,R = 2
  • @doanduyhai#C*ModelisationAvancee 11:Martin, 85:Sophie, 57:Smith Implémentation Mais pourquoi ???  range scan pour lire les données  …de toute façon n4 n3 n2 n1 DE → {18} US → {25,74} FR → {10,11,85} UK → {57} 10:Dupond, 25:John, 18:Heinrich 74:Helen 201
  • @doanduyhai#C*ModelisationAvancee Use-cases recommandés Bon candidats  peu de valeurs indexées # (mais assez quand même) 202
  • @doanduyhai#C*ModelisationAvancee Use-cases recommandés Bon candidats  peu de valeurs indexées # (mais assez quand même) Mauvais candidats  très peu de valeurs indexées # (index d’un booléen )  beaucoup de valeurs indexées # (index sur email )  m.a.j./suppression fréquentes  très gros cluster 203
  • @doanduyhai#C*ModelisationAvancee Retour d’expérience Queue pour état d’avancement  états : { ‘TODO’, ‘IN PROGRESS’, ‘PROCESSED’, ‘DONE’}  colonne : item_id/état  index secondaire sur état 204
  • @doanduyhai#C*ModelisationAvancee Retour d’expérience Queue pour état d’avancement  états : { ‘TODO’, ‘IN PROGRESS’, ‘PROCESSED’}  colonne : item_id/état  index secondaire sur état Transition  prendre 1000 items avec état ‘TODO’  m.a.j. de l’état en ‘IN PROGRESS’  traiter les items  mettre les 1000 états en ‘PROCESSED’  si erreur, remettre état en ‘TODO’ 205
  • @doanduyhai#C*ModelisationAvancee Retour d’expérience Solution  utiliser JMS pour queue  queue avec wide row, bucketing & accès concurrent  compteur pour messages réinjectés  enlever index secondaires 206
  • @doanduyhai#C*ModelisationAvancee Q & R  
  • @doanduyhai#C*ModelisationAvancee <FUTUR> C* Requêtes inter-clustering Colonnes statiques User defined type
  • @doanduyhai#C*ModelisationAvancee Requêtes inter-clustering (2.0.6) Données CREATE TABLE notes_film ( film_id uuid, note uuid, user_id int, commentaire text, PRIMARY KEY(film_id, note, user_id)); Note User_id Commentaire 1 10 Bla bla bla … … … 1 49 Bla bla bla 1 82 Bla bla bla 2 13 Bla bla bla 2 54 Bla bla bla 3 15 Bla bla bla 11 notes de valeur 1 209
  • @doanduyhai#C*ModelisationAvancee Requêtes inter-clustering (2.0.6) Pagination par 10  user_id 10 à 49 SELECT * FROM notes_film WHERE film_id=.. AND note=1 LIMIT 10 210 Note User_id Commentaire 1 10 Bla bla bla … … … 1 49 Bla bla bla 1 82 Bla bla bla 2 13 Bla bla bla 2 54 Bla bla bla 3 15 Bla bla bla 11 notes de valeur 1
  • @doanduyhai#C*ModelisationAvancee Requêtes inter-clustering (2.0.6) Deuxième page  user_id 82 SELECT * FROM notes_film WHERE film_id=.. AND note=1 AND user_id>49 LIMIT 10 211 Note User_id Commentaire 1 10 Bla bla bla … … … 1 49 Bla bla bla 1 82 Bla bla bla 2 13 Bla bla bla 2 54 Bla bla bla 3 15 Bla bla bla 11 notes de valeur 1
  • @doanduyhai#C*ModelisationAvancee Requêtes inter-clustering (2.0.6) Solution naïve (à la SQL) SELECT * FROM notes_film WHERE film_id=.. AND note≥1 AND user_id>49 LIMIT 10 212 Note User_id Commentaire 1 10 Bla bla bla … … … 1 49 Bla bla bla 1 82 Bla bla bla 2 13 Bla bla bla 2 54 Bla bla bla 3 15 Bla bla bla
  • @doanduyhai#C*ModelisationAvancee Requêtes inter-clustering (2.0.6) Nouvelle syntaxe SELECT * FROM notes_film WHERE film_id=.. AND (note,user_id) > (1,49) LIMIT 10 213 Note User_id Commentaire 1 10 Bla bla bla … … … 1 49 Bla bla bla 1 82 Bla bla bla 2 13 Bla bla bla 2 54 Bla bla bla 3 15 Bla bla bla
  • @doanduyhai#C*ModelisationAvancee Colonnes statiques (2.0.6) CREATE TABLE notes_film ( film_id uuid, note uuid, user_id int, commentaire text, PRIMARY KEY(film_id, note, user_id)); CREATE TABLE films ( film_id uuid, titre text, synopsis text, acteurs_id set<int>, acteurs set<text> PRIMARY KEY(film_id)); 214
  • @doanduyhai#C*ModelisationAvancee Colonnes statiques (2.0.6) Afficher le film et les notes  1 requête pour film  1 requête pour notes 215
  • @doanduyhai#C*ModelisationAvancee Colonnes statiques (2.0.6) Objectif: 1 seule requête Solution naïve CREATE TABLE notes_film ( film_id uuid, note uuid, user_id int, titre text, synopsis text, acteurs_id set<int>, acteurs set<text>, commentaire text, PRIMARY KEY(film_id, note, user_id)); 216
  • @doanduyhai#C*ModelisationAvancee Colonnes statiques (2.0.6) RowKey: 98bc1cec-4c4b-468b-a20e-2af142a26c97 => (column=1:10:, value=, …) => (column=1:10:titre, value=…) => (column=1:10:synopsis, value=…) => (column=1:10:acteurs_ids, value=…) => (column=1:10:acteurs, value=…) => (column=1:10:commentaire, value=‘Quel navet! Passez votre chemin, vous …’, …) => (column=1:23:, value=, …) => (column=1:23:titre, value=…) => (column=1:23:synopsis, value=…) => (column=1:23:acteurs_ids, value=…) => (column=1:23:acteurs, value=…) => (column=1:23:commentaire, value=‘Un film à regarder avec le cerveau débranché’, …) 217
  • @doanduyhai#C*ModelisationAvancee Colonnes statiques (2.0.6) Avec colonnes statiques CREATE TABLE notes_film ( film_id uuid, note uuid, user_id int, titre text static, synopsis text static, acteurs_id set<int> static, acteurs set<text> static, commentaire text, PRIMARY KEY(film_id, note, user_id)); 218
  • @doanduyhai#C*ModelisationAvancee Colonnes statiques (2.0.6) RowKey: 98bc1cec-4c4b-468b-a20e-2af142a26c97 => (column=:null:null:titre, value=…) => (column=:null:null:synopsis, value=…) => (column=:null:null:acteurs_ids, value=…) => (column=:null:null:acteurs, value=…) => (column=1:10:, value=, …) => (column=1:10:commentaire, value=‘Quel navet! Passez votre chemin, vous …’, …) => (column=1:23:, value=, …) => (column=1:23:commentaire, value=‘Un film à regarder avec le cerveau débranché’, …) 219
  • @doanduyhai#C*ModelisationAvancee User defined type (2.1) CREATE TABLE commentaires ( article_id int, date_creation timestamp, auteur user, contenu text, PRIMARY KEY (article_id, date_creation)); CREATE TYPE user ( id int, nom text, adresse text, bio text); 220
  • @doanduyhai#C*ModelisationAvancee User defined type (2.1) Syntaxe INSERT INTO commentaires(article_id,date_creation,auteur,contenu) VALUES( 10, 2014-04-16 10:00:00+0100, { id: 156, nom: ‘Pierre DUPOND’, adresse: ‘12 rue de la Paix 75016 PARIS’, bio: ‘Je suis un habitant du 16ème…’ }, ‘Cet article a trop de fautes d’orthographe…’); 221
  • @doanduyhai#C*ModelisationAvancee User defined type (2.1) Imbrication arbitraire CREATE TYPE user ( id int, nom text, adresse location, bio text); CREATE TYPE location ( numero int, voie text, code_postal int, ville text); 222
  • @doanduyhai#C*ModelisationAvancee User defined type (2.1) Limitations  modifications non atomiques  lecture eager  ALTER TYPE ADD, ALTER TYPE RENAME 223
  • @doanduyhai#C*ModelisationAvancee User defined type (2.1) Sélection possible sur les champs internes UDT ≈ blob SELECT auteur.nom, auteur.adresse, contenu FROM commentaires … 224
  • @doanduyhai#C*ModelisationAvancee User defined type (2.1) Colonnes d’agrégation (clustering)  tri → ordre du type des champs déclarés Collections & Maps  unicité → comparaison des champs déclarés dans l’ordre 225
  • @doanduyhai#C*ModelisationAvancee MERCI ! @doanduyhai doanduyhai@gmail.com doanduyhai