Cassandra

Transcript

Cassandra
Cassandra
Cassandra
Introduzione
Nasce inizialmente all'interno di Facebook per gestire le ricerche fra i messaggi.
Attualmente open-source, è uno dei database NoSQL più diffusi.
E' incluso tra i database NOSQL Column family perché ha un datamodel ispirato a
BigTable, tuttavia presenta delle differenze sostanziali rispetto ad HBase.
Infatti, Cassandra :
●
oltre alla column family ha anche le super column family;
●
ha un'infrastruttura ispirata a Amazon Dynamo (key-value store);
●
è decentralizzato, ovvero ogni nodo del cluster ha lo stesso ruolo;
●
si può scegliere il livello di consistenza dei dati (teorema CAP);
●
ha un proprio linguaggio di interrogazione stile SQL: il CQL.
Cassandra
Data Model
Il datamodel di Cassandra è abbastanza simile a quello HBase per il modello base di
column family, che illustriamo nuovamente qua sotto per comodità:
Column family
Una colonna avrà quindi una key (row + column family), un valore ed un timestamp.
Cassandra
Data Model
A differenza di HBase, però, Cassandra ha anche le Super Column Family. Queste
permettono di aggiungere una ulteriore dimensione alla mappa e rappresentano un
gruppo di colonne correlate fra di loro come illustrato quando abbiamo introdotto i DB
NoSQL.
Attualmente però le SuperColumn in Cassandra sono sempre meno usate in quanto
non molto performanti e l'impossibilità di indicizzare le subcolumn all'interno di una
super column.
Per superare questo problema sono
state introdotte le composite column
che vedremo più avanti quando
parleremo di CQL.
Cassandra
Data Model
Nel datamodel di Cassandra, individuiamo 4 entità ben definite che sono:
Nome
Definizione breve
Analogia RDBMS
Keyspace
Una collezione di Column Family.
Database
Column Family Un insieme di row.
Tabella
Row
Un insieme ordinato di Column.
Riga
Column
Una coppia chiave/valore con timestamp
associato.
Colonna
Il keyspace è un namespace che definisce come i dati vengono replicati nei nodi. Tipicamente
in un cluster esiste un solo keyspace per applicazione.
Vedremo maggiori dettagli su queste entità quando più avanti descriveremo il CQL.
Cassandra
Architettura
Cassandra ha un'architettura completamente distribuita e decentralizzata.
Con decentralizzata si intende che non esiste un “single point of failure”. Tutti i nodi in
un cluster Cassandra hanno gli stessi compiti e funzionalità (“server simmetry”), ad
esempio non esiste un nodo specifico che si occupa di coordinare le attività del cluster.
La decentralizzazione ha due vantaggi: è più semplice da usare rispetto ad una
architettura master/slave (la comunicazione è peer-to-peer) e permette di evitare
disservizi (indisponibilità) in maniera più semplice.
Cassandra
Architettura
Il modello di distribuzione peer-to-peer permette di aggiungere e/o rimuovere nodi
senza problemi (con strategia di replica adeguata). Quando un nodo viene aggiunto al
cluster per prima cosa individua la topologia dello stesso e riceve i dati per i quali sarà
responsabile, successivamente potrà accettare le richieste dai client.
In questo modo si ottiene una elastic scalability con performance che scalano in
maniera lineare ed i dati sono sempre distribuiti in modo bilanciato.
Cassandra
Architettura
I cluster in Cassandra sono anche detti ring per l'architettura ad anello che li
caratterizza.
L'anello rappresenta l'andamento ciclico dello spazio dei token, il token viene generato
in base alla chiave di riga e serve ad individuare in quale nodo è memorizzato il dato.
Ad ogni nodo è assegnata una posizione nell'anello basata sui token che deve gestire.
Ciascun nodo è responsabile per tutti i token fra il suo token iniziale ed il token iniziale
del nodo più vicino nell'anello.
Cassandra
Architettura
Per mappare le chiavi di riga nello spazio dei token viene usato un partitioner.
I partitioner di base sono due: un random partitioner ed un order preserving partitioner.
Nel primo caso il token viene generato attraverso una funzione hash MD5 e le chiavi vengono
distribuite nel cluster non mantenendo l'ordine delle chiavi (è il partitioner di default). Questo
permette di bilanciare il carico fra i nodi.
Se invece si opta su un order preserving partitioner in questo caso viene mantenuto l'ordine fra le
chiavi anche nei token. Ad esempio se le chiavi sono A, B e C allora si deve avere che token(A) <
token(B) < token(C).
Questo può portare ad avere uno sbilanciamento di informazioni fra i nodi, ma consente di
ottimizzare gli accessi nel caso in cui si debbano recuperare i dati ordinati.
Cassandra
Architettura
Un'altra caratteristica importante di Cassandra è la Failure Tolerance. Questa può
essere impostata indicando il replica factor nel keystore.
Il replica factor indica il numero dei nodi nel quale deve essere mantenuto il dato. Si
noti che i nodi sono successivi secondo la topologia dell'anello.
Cassandra
Architettura
Le strategie di replication esistenti sono due:
●
SimpleStrategy: si ha un solo datacenter, i dati sono memorizzati in nodi
successivi sull'anello;
●
NetworkTopologyStrategy: si hanno più datacenter, i dati sono trasmessi a tutti i
datacenter, in ognuno di essi i dati sono memorizzati in nodi successivi in base al
partitioner selezionato su quel datacenter.
Si noti che i datacenter sono fra di loro “indipendenti” nel senso che possono avere
parametri ed impostazioni differenti (ad esempio possono avere un replica factor
diverso).
Cassandra
Architettura
Oltre al replica factor, l'altro fattore importante per la memorizzazione dei dati in
Cassandra è la consistency. Questa è modificabile a run-time sia in lettura che scrittura.
Le strategie possibili sono:
●
ANY (Solo in scrittura)
●
ONE
●
TWO
●
THREE
●
QUORUM
●
LOCAL_QUORUM (quorum all'interno dello stesso datacenter)
●
EACH_QUORUM (quorum in tutti i datacenter)
●
ALL
Cassandra
Architettura
Consistency ONE.
Scrittura Il nodo coordinatore (quello a cui si è collegato il
client) scrive in tutti i nodi dove risiede la replica del dato;
aspetta l'ack del primo nodo per rispondere al client; gli ack
degli altri nodi arrivano in maniera asincrona.
Lettura Il nodo coordinatore legge il dato dal nodo più
veloce che contiene la replica.
Cassandra
Architettura
Consistency QUORUM (maggioranza assoluta fra le repliche)
Scrittura Il nodo coordinatore (quello a cui si è collegato il
client) scrive in tutti i nodi dove risiede la replica del dato;
aspetta l'ack dal quorum dei nodi per rispondere al client; gli
ack degli altri nodi arrivano in maniera asincrona.
Lettura Il nodo coordinatore legge il dato dal nodo più veloce
e chiede un digest alle repliche; appena ha avuto risposta dal
quorum dei nodi restituisce il dato più aggiornato; aggiorna il
dato memorizzato nelle repliche.
Cassandra
Architettura
La consistency può essere diversa fra lettura e scrittura. Vediamo meglio con un
esempio di cosa succede in diverse combinazioni.
RF = 3, write ONE, read ONE
Write ONE: V1
Node 1
V1
Read ONE: V0
Replication
in progress
Node 2
Node 3
V0
V0
Cassandra
Architettura
RF = 3, write ONE, read Quorum
Write ONE: V1
Node 1
V1
Read Quorum: V0
Replication
in progress
Node 2
Node 3
V0
V0
Cassandra
Architettura
RF = 3, write ONE, read ALL
Write ONE: V1
Node 1
V1
Read ALL: V1
Replication
in progress
Node 2
Node 3
V0
V0
Cassandra
Architettura
RF = 3, write Quorum, read ONE
Write Quorum: V1
Read ONE: V0
Node 1
Node 2
V1
V1
Replication
in progress
Node 3
V0
Cassandra
Architettura
RF = 3, write Quorum, read Quorum
Write Quorum: V1
Read Quorum: V1
Node 1
Node 2
V1
V1
Replication
in progress
Node 3
V0
Cassandra
Architettura
RF = 3, write Quorum, read ALL
Write Quorum: V1
Read ALL: V1
Node 1
Node 2
V1
V1
Replication
in progress
Node 3
V0
Cassandra
CQL
A differenza di molti altri database NoSQL Cassandra dispone di un proprio linguaggio
di query, in versione beta sin dalla versione 0.8.0.
Il Cassandra Query Language, CQL3, è arrivato alla sua terza versione ed è diventato
l'API di interrogazione dei dati predefinita e la precedente API, la CLI, è ormai
deprecata e verrà rimossa a partire dalla versione 3.x di Cassandra.
L'assonanza nel nome vuole richiamare le forti similitudini con SQL.
Il CQL può essere utilizzato via API o attraverso una shell cqlsh.
Cassandra
CQL – Creare un DB
Semplificando, un DB è una collezione di tabelle; l'equivalente in Cassandra prende il nome di
keyspace, che inoltre definisce anche una strategia di replica dei dati:
il keyspace è un namespace che definisce come i dati vengono replicati nei nodi
Esistono due strategie a seconda che si utilizzi un solo cluster (SimpleStrategy) o più cluster
(NetworkTopologyStrategy). La sintassi per creare un keyspace è la seguente
CREATE
KEYSPACE
[keyspace_name]
WITH
REPLICATION
=
{'class'
:
'Strategy', [datacenter_name] : n };
Dove keyspace_name è il nome che si vuole dare al keyspace ed n indica il numero di repliche
di dati che deve essere presente nel cluster.
Cassandra
CQL – Creare un DB
Nel caso di un solo datacenter non è necessario assegnargli un nome e la stringa associata
CREATE
KEYSPACE
keyspace_name
WITH
REPLICATION
=
{'class'
:
'SimpleStrategy', 'replication_factor' : n };
Nel caso di più datacenter è necessario specificare il nome del datacenter ed il replica_factor per
ciascuno di essi:
CREATE
KEYSPACE
keyspace_name
WITH
REPLICATION
=
'NetworkTopologyStrategy', 'dataprim' : 3 , 'datas' : 2 };
{'class'
:
Cassandra
CQL – Lavorare con un Keyspace
E' possibile selezionare un keyspace per lavorare solo con le tabelle di un particolare DB:
USE keyspace_name;
oppure modificarlo, ad esempio per cambiare il replication factor od aggiungere datacenter,
attraverso il comando ALTER KEYSPACE che segue la sintassi di CREATE KEYSPACE.
Inoltre è possibile ottenre l'elenco di tutti i keyspace con il comando
DESCRIBE KEYSPACES;
o alternativamente interrogando la tabella system (che contiene i metadati ) :
SELECT * FROM system.schema_keyspaces;
Cassandra
CQL – Creare una Tabella
Lo sviluppo di Cassandra sta procedendo a ritmi serrati ed è in corso una grande
rivoluzione concettuale per trasformarlo in uno strumento di facile utilizzo per chi si
occupa di analisi di dati ma non è interessati ai dettagli implementativi.
Per questo è in corso una forte trasformazione del CQL per renderlo sempre più simile
al SQL e farlo diventare l'unico sistema di interrogazione dati.
Ad esempio “di fatto” è stato deprecato l'uso delle Super Column Families perché
rendevano complicata ed inefficiente la costruzione di indici secondari ed altre
ottimizzazioni, e si sta mascherando l'uso delle Column Families con l'analogia
Column Family == SQL Table
Cassandra
CQL – Creare una Tabella
La sintassi per la creazione di tabelle (ovvero le column family) è la seguente:
CREATE TABLE keyspace_name.table_name
( column_definition, column_definition, ...)
WITH property AND property ..
Il keyspace_name può essere omesso se si deve creare una tabella nel keyspace attualmente
in uso; e column_definition può seguire uno dei seguenti formati :
●
column name cql_type
●
column name cql_type PRIMARY KEY
●
PRIMARY KEY (partition key)
●
column name collection_type
Cassandra
CQL – Tipi di Dati
I cql_type e collection_type supportati sono:
Cassandra
CQL – Collection Types
La collection_type sono di tre tipi :
●
LIST <cql_type>
●
SET <cql_type>
●
MAP <cql_type, cql_type>
Le collection non possono essere annidate, ovvero non può esistere una lista di liste.
Sono utili per gestire associazioni multiple (es. più indirizzi email, i tag di una foto) e consentono
delle semplici denormalizzazioni sui dati; ma la dimensione del loro contenuto è limitata a 64K.
Quindi non sono adatte per dati che possono crescere indefinitamente come ad esempio tutti i
post di un utente o gli eventi registrati da un sensore.
In questi casi è necessario utilizzare le compound primary key che vedremo a breve.
Cassandra
CQL – Primary Key
La primary key (ovvero la row key, quella con cui saranno indicizzati i dati di una tabella) può
essere specificata in due modi :
●
column name cql_type PRIMARY KEY
●
PRIMARY KEY (partition key)
I dati di tutte le colonne saranno memorizzati garantendo la loro prossimità su disco; che
schematicamente si può rappresentare nel seguente modo:
Table (column family)
Primary key (row key)
Column name 1 Column data
Column name 2 Column data
Column name 3 Column data
Column name 4 Column data
Cassandra
CQL – Compound Primary Key
Se si specificano più primary key separate da “,” si parla di compound primary key.
●
PRIMARY KEY (partition key, clustering column, ...)
In questo caso la prima chiave sarà la partition key e le altre sono chiamate clustering column.
Su disco le colonne che hanno la stessa partition key sono fisicamente memorizzate nello stesso
nodo e le clustering column sono utilizzate per clusterizzare i dati ovvero i dati vengono
memorizzati in modo ordinato rispetto alle clustering column.
Table (column family)
Partition key
Cluster Col Val1 : Column name 1
Column data
Cluster Col Val1 : Column name 2
Column data
Cluster Col Val1 : Column name 3
Column data
Cluster Col Val2 : Column name 1
Column data
Cassandra
CQL – Compound Primary Key
Un esempio più dettagliato è il seguente
CREATE TABLE Posts (email_id text, post_id timeuuid, name text, body
text, posted_at timestamp, PRIMARY KEY (email_id,post_id))
Se inserisco dei dati questi verranno memorizzati così:
Posts
Partition key:
20150218_132000 : name
[email protected]
20150218_132000 : body
Nicola
Bla bla bla ….
20150218_132000 : posted_at
2015-02-18 13:20:00
20150216_112012 : name
Maurizio
20150216_112012 : body
Bla2 bla2 bla2 ….
20150216_112012 : posted_at
2015-02-16 11:20:12
Cassandra
CQL – Composite Partitition Key
Il vincolo di dover memorizzare su uno steso nodi tutti i dati appartenenti ad una stessa
partition key può essere limitante per la distribuzione dei dati.
Per superare questo limite si possono usare anche le composite partition key che
consentono di suddividere la row key in due parti:
PRIMARY
KEY
((partition
key1,
partition
key2),
clustering
column, …)
in questo modo solo le colonne con gli stessi valori di (key1, key2) dovranno trovarsi
su uno stesso nodo, mentre tutti le altre potranno essere distribuite su nodi diversi .
Cassandra
CQL – Inserimento Dati
Per inserire dei dati all'interno delle tabelle dobbiamo utilizzare il comando INSERT
INSERT INTO keyspace_name.table_name
( column_name, column_name...)
VALUES ( value, value ... )
USING option AND option
I valori devono rispettare la tipologia specificata per la colonna, se si tratta di dati testuali devono
essere racchiusi fra apici.
Una operazione di INSERT inserisce una o più colonne in una tabella di Cassandra in maniera
atomica ed isolata (nel senso delle proprietà ACID).
Cassandra
CQL – Inserimento Dati
Per inserire dati nelle collection i valori devono essere specificati all'interno di parentesi [] nel caso
di liste, {} di set e mappe.
LIST
SET
MAP
→
→
→
[value, value …]
{value, value …}
{value_key : value, value_key : value …}
E' bene precisare che in CQL:
●
le list servono per memorizzare valori univoci e ordinati; i valori possono essere inseriti in
qualunque ordine e verranno restituiti secondo il loro ordinamento naturale (es. alfabetico);
●
i set consentono di inserire duplicati ed i valori verranno restituiti secondo l'ordine di
inserimento;
Cassandra
CQL – Timestamp e TTL
In Cassandra ad ogni dato memorizzato è associato un timestamp (in microsecondi)
che indica l'istante di creazione, se non specificato viene utilizzato quello effettivo di
inserimento della colonna.
Inoltre è possibile associare un time to leave (TTL) in secondi che indica dopo tempo il
dato potrà essere automaticamente cancellato (utile ad esempio per la creazione di
tabelle temporanee o viste sui dati)
INSERT INTO Hollywood.NerdMovies (user_uuid, fan)
VALUES (cfd66ccc-d857-4e90-b1e5-df98a3d40cd6, 'johndoe')
USING TTL 86400;
Cassandra
CQL – Aggiornamento dei Dati
Per aggiornare dei dati si può usare il comando UPDATE.
UPDATE keyspace_name.table_name
USING option AND option
SET assignment, assignment, …
WHERE row_specification
Le option che si possono specificare sono timestamp e time to leave.
Nel caso di list e set è possibile anche aggiungere elementi, mentre nel caso di map questa
collection può essere solamente sostituita con una nuova.
UPDATE table_name SET set_name = set_name + {'value'}
UPDATE table_name SET list_name = list_name + ['value']
Cassandra
CQL – Ricerca e selezione dei Dati
Per interrogare i dati si utilizza il comando SELECT.
SELECT selector
FROM keyspace_name.table_name
WHERE relation AND relation ...
ORDER BY ( clustering_column ( ASC | DESC )...)
LIMIT n
ALLOW FILTERING
Il selector può essere la combinazione di questi elementi
column name
Uno o più nomi di colonne da visualizzare separati da
virgola
COUNT (*)
Conteggio degli elementi restituiti
WRITETIME (column_name)
Timestamp associato alla colonna
TTL (column_name)
Time to leave della colonna
Cassandra
CQL – Batch Operations
Un'altra funzionalità interessante di Cassandra sono le Batch operations.
Queste permettono di raggruppare operazioni di Data Manipulation Language (INSERT,
UPDATE, DELETE) ed eseguirle in un solo passo, in maniera simile alle transazioni
RDBMS.
Infatti, le operazioni batch sono atomiche, quindi o vengono eseguite tutte con
successo oppure i dati non vengono manipolati.
Inoltre, tutte le operazioni all'interno di un batch avranno lo stesso timestamp (ma
possono avere TTL diverso).
Cassandra
CQL == SQL ?
Quindi col CQL posso sostituire SQL?
Attualmente no!
Il CQL è in rapida evoluzione e si avvicinando sempre più al SQL, ma è ancora molto
distante in quanto:
●
È privo di funzionalità di aggregazione (es. GROUP BY)
●
Il WHERE non è libero, ma posso usare solo certi operatori di filtraggio e solo su
colonne particolari (es. >=, <= possono essere usati solo sulle clustering column)
●
Sulla partition key posso usare solo la condizione di uguaglianza
●
Non esiste DISTINCT o costrutti simili
●
Etc...