NoSQL Databases
NoSQL Databases
NoSQL Databases
Massimo Carro
Politecnico di Milano
Piazza
Leonardo
da
Vinci
32
20133
Milano
[email protected]
1. Introduzione
L’arrivo
di
internet
negli
anni
90
ha
permesso
a
molte
aziende
di
ampliare
il
proprio
bacino
di
utenza
portando
online
un’enorme
quantità
di
contenuti
e
servizi;
il
caso
più
esemplare
che
possiamo
citare
è
Amazon,
nata
solo
nel
1994
ma
con
un
fatturato
attestato
a
61
miliardi
di
dollari
nel
2012[1].
Di
conseguenza,
la
quantità
dei
dati
presenti
sulla
“rete”
è
aumentata
esponenzialmente
dai
20TB
del
1994
passando
dai
681PB
nel
2003
fino
ai
31.338PB
del
2012[2],
come
si
può
vedere
dal
grafico
in
figura
1.
Traffico
Internet
35000
30000
25000
PB/Mese
20000
15000
PB/Mese
10000
5000
0
1995
1997
1998
1999
2001
2005
2007
2008
2009
2011
1994
1996
2000
2002
2003
2004
2006
2010
2012
Tempo
Figure 1 - Evoluzione del traffico su internet negli ultimi 20 anni.
Questo
ha
fatto
si
che
i
sistemi
informatici
debbano
elaborare
molte
più
informazioni
e
quindi
maggiore
potenza
di
calcolo,
mentre
i
dati,
sempre
più
numerosi,
maggiore
possibilità
di
organizzazione.
Negli
ultimi
anni
con
l’avvento
del
web
2.0,
sono
aumentate
le
aziende
che
operano
esclusivamente
online
(si
pensi
a
Facebook
ed
a
FourSquare
ad
esempio)
fornendo
contenuti
sempre
più
numerosi
e
strutturati;
la
disponibilità
e
affidabilità
dei
servizi
unita
alla
capacità
di
gestire
una
grande
mole
di
contenuti
e
fortemente
correlati
è
diventato
un
requisito
imprescindibile.
Sempre
più
spesso
le
aziende
on-‐line
e
off-‐line
hanno
reso
più
stringenti
gli
SLA
(Service
Level
Agreement)
traducendo
a
livello
contrattuale
le
aspettative
dell’utente
finale,
ovvero
che
il
servizio
sia
sempre
disponibile,
facilmente
accessibile
(sia
come
tempi
di
risposta
che
come
usabilità)
e
possibilmente
attendibile.
La
tendenza
è
diventata
quella
di
garantire
più
il
servizio
o
il
contenuto
rispetto
della
correttezza
delle
informazioni
o
alla
consistenza
dei
dati,
fatta
eccezione
dei
casi
di
servizi
sotto
protocollo
sicuro:
ad
esempio
il
settore
bancario,
l’e-‐governance
o
alcune
fasi
di
sicurezza
dei
dati
nell’e-‐
commerce.
I
fautori
di
questo
nuovo
approccio
sono
stati
Google
e
Amazon
con
i
loro
sistemi
proprietari
(rispettivamente
BigTable
e
Dynamo)
ma
da
subito,
soprattutto
in
ambito
“social”,
si
sono
sviluppati
sistemi
di
gestione
equiparabili
e
diversi
dai
DBMS
Relazionali
(da
ora:
RDBMS).
A
questi
nuovi
sistemi
è
stato
dato
il
nome
di
DBMS
NoSql
(da
ora:
NoSql)
proprio
per
specificare
cosa
viene
a
mancare,
sia
come
garanzia
che
come
rigidità:
le
relazioni.
L’oggetto
di
questa
analisi
sono
quindi
i
database
NoSql:
ne
analizzeremo
le
caratteristiche,
i
principi
fondanti
e
le
opportunità
che
offrono
rispetto
ad
un
RDBMS.
Analizzeremo
quindi
la
struttura
di
alcuni
NoSql
per
capire
come
si
differenziano
tra
di
loro
in
funzione
dell'uso
che
se
ne
vuole
fare.
Forniremo
inoltre
un
dettaglio
più
pratico
e
operativo
di
alcuni
NoSql
(MongoDB,
Riak,
Cassandra,
e
Neo4j),
mostrando
tramite
delle
tabelle
comparative
i
risultati
dei
test
effettuati.
Le
motivazioni
personali
che
mi
hanno
spinto
a
questa
analisi
nascono
dalla
convinzione
che
questa
metodologia
di
mantenimento
ed
uso
delle
informazioni
sia
un’alternativa
spesso
sottovalutata
in
ambito
aziendale,
mentre
l’utilizzo
di
questi
sistemi
hanno
portato
a
casi
di
successo
ormai
noti
come
i
già
citati
Facebook,
Amazon,
ma
anche
LinkedIn,
Ebay
e
in
ambito
nazionale
Blogo.
1.1. Contributi
Dopo
una
breve
introduzione
delle
caratteristiche
salienti
di
DBMS
Relazionali
e
NoSQL,
ci
focalizzeremo
su
questi
ultimi
per
andare
nel
dettaglio
ed
analizzare
come
vengono
garantite
la
disponibilità
delle
informazioni,
la
gestione
della
concorrenza,
la
consistenza
dei
dati
e
la
scalabilità.
Quello
che
vogliamo
approfondire
sono
le
caratteristiche
dei
database
NoSQL;
lo
faremo
mostrando
le
differenze
che
le
varie
classificazioni
(Capitolo
5)
hanno
tra
di
loro
utilizzando
specifici
DBMS
quali
MongoDB,
Riak,
Cassandra
e
Neo4i,
uno
per
ogni
categoriaa.
Ci
si
focalizzerà
poi
sulla
realizzazione
di
un
cluster
per
ognuno
di
essi,
grazie
al
quale
potremo
vedere
come
i
dati
possono
essere
archiviati
e/o
recuperati
e
come
essere
distribuiti
nel
cluster
passando
dal
concetto
di
replica
a
quello
di
sharding.
Tramite
un
inserimento
massivo
vedremo
infine
i
tempi
necessari
ad
inserire
le
informazioni
per
ognuno
di
essi
e
il
carico
che
le
macchine
devono
sopportare.
Alla
fine
le
conclusioni
evidenzieranno
pregi
e
difetti
di
ogni
tipologia
esaminata,
nonché
una
breve
considerazione
sugli
ambiti
di
competenza
per
gli
stessi.
a
La
scelta
è
ricaduta
su
questi
specifici
NoSQL
perché
ora
molto
in
voga
e
open-‐source.
2.1.1. ACID
Le
proprietà
acide
indicano
le
caratteristiche
che
devono
avere
le
transazioni
per
essere
tali.
• (A)tomicity
–
Atomicità
L’esecuzione
della
transazione
deve
essere
o
totale
o
nulla:
quindi
o
si
riesce
ad
applicare
tutto
quello
che
la
transizione
vuole
che
venga
cambiato
o
la
transizione
stessa
viene
disfata;
nascono
i
concetti
di
commit
e
rollback.
• (C)onsistency
-‐
Coerenza
Quando
inizia
la
transazione
il
sistema
si
deve
trovare
in
uno
stato
coerente
e
anche
quando
termina:
chiaramente
dipendentemente
dal
livello
di
isolamento
adottato;
vengono
quindi
garantiti
i
vincoli
di
integrità
dei
dati.
• (I)solation
-‐
Isolamento
Ogni
transazione
è
indipendente
dalle
altre.
Il
suo
fallimento
non
deve
provocare
danni
ad
altre
transazioni.
• (D)urability
-‐
Persistenza
Al
commit
della
transazione,
le
modifiche
apportate
dalla
stessa
non
dovranno
essere
perse
in
nessun
modo.
Figure 2 – Rappresentazione grafica del teorema di CAP ed esempi di adattamento di alcuni strumenti.
Le
proprietà
BASE
rinunciano
alla
consistenza
per
garantire
disponibilità
dell’informazione
e
scalabilità.
L’acronimo
indica
le
caratteristiche
che
un
sistema
deve
garantire
sottostando
al
teorema
di
CAP.
• (B)asically
(A)vailable
Il
sistema
deve
garantire
la
disponibilità
delle
informazioni.
• (S)oft
State
Il
sistema
può
cambiare
lo
stato
nel
tempo
anche
se
non
sono
presenti
letture
o
scritture.
• (E)ventual
consistency
In
sistema
può
diventare
consistente
nel
tempo,
anche
senza
ricevere
scritture
o
quant’altro,
grazie
a
dei
sistemi
di
recupero
della
consistenza.
Fondamentalmente
possiamo
riassumere
le
tre
proprietà
precedenti
dicendo
che:
quando
la
disponibilità
dell’informazione
è
prioritaria,
è
possibile
lasciare
che
l'applicativo
scriva
su
un
nodo
quello
che
deve
scrivere
senza
che
si
riceva
un
ok
della
propagazione
di
queste
scritture
sugli
altri
nodi
in
cui
ci
si
aspetta
venga
replicato.
Questo
fa
si
che
si
raggiungano
alti
livelli
di
disponibilità
(non
ci
sono
tempi
di
attesa)
a
fronte
di
quella
che
definiamo
eventual
consistency
ovvero
la
capacità
del
sistema
di
saper
sistemare
le
informazioni
sui
vari
nodi,
col
passare
del
tempo,
in
maniera
asincrona.
2.2.2 Scalabilità
Un
database
NoSql,
d’altra
parte,
è
più
versatile
a
livello
di
scalabilità
orizzontale,
cosa
che
un
RDBMS
non
può
garantire;
anzi,
quest’
ultimo
per
diventare
sempre
più
“grande”
(nel
senso
di
contenere
sempre
più
informazioni)
ha
necessità
di
scalare
verticalmente
e
quindi
di
avere
a
disposizione
hardware
sempre
più
performante
e
costoso.
I
database
NoSQL
ci
consentono
di
usare
macchine
molto
comuni
e
non
troppo
costose,
potendo
suddividere
le
informazioni
su
di
esse.
cambia;
la
suddivisione
dei
carichi
tra
le
macchine
del
cluster
fa
si
che
i
server
possano
essere
costruiti
con
hardware
di
costo
più
appetibile.
• Correlazione
dei
dati
Ad
esclusione
di
casi
ad
hoc
(come
vedremo
per
Neo4j)
si
cerca
di
far
si
che
sia
l'applicativo
a
correlare
le
informazioni
se
necessario;
si
cerca
di
mantenere
esclusivamente
una
correlazione
se
vantaggiosa
(come
di
vedrà
con
Cassandra).
Inoltre
molti
sono
gli
studi
sui
database
NoSql
al
fine
di
migliorare:
• Performance
Vengono
continuamente
studiati
algoritmi
atti
a
migliorare
complessivamente
le
prestazioni
dei
NoSQL.
• Scalabilità
Orizzontale
L'aggiunta
di
macchine
e
la
rimozione
delle
stesse
dal
cluster,
deve
avvenire
senza
troppa
difficoltà
e
soprattutto
senza
che
il
sistema
debba
essere
fermato
o
subire
momentanei
rallentamenti.
• Performance
sulla
singola
macchina
Oltre
a
tener
da
conto
la
scalabilità
orizzontale,
vengono
effettuati
studi
per
migliorare
le
prestazioni
anche
sulle
singole
macchine,
le
quali
sono
in
molti
casi
artefici
di
ricerca
di
informazioni
nel
cluster
su
richiesta
degli
applicativi.
• Disponibilità
delle
informazioni
(Availability)
Un
sistema
è
costruito
in
maniera
tale
che,
se
un
nodo
dovesse
venire
a
mancare
per
qualunque
motivo,
questa
situazione
non
blocca
il
sistema.
• Partition
tolerance
Il
sistema
continua
a
operare
anche
in
seguito
ad
un
partizionamento
della
rete,
inteso
come
caso
in
cui
due
isole
di
partizioni
non
riescano
più
a
colloquiare
fra
di
loro.
Correlato
alla
replica
è
lo
sharding,
ovvero
il
partizionamento
dei
dati,
o
se
si
preferisce
la
suddivisione
in
blocchi
degli
stessi
sui
vari
nodi
appartenenti
al
sistema.
Con
lo
sharding
è
possibile
suddividere
e
distribuire
i
dati
su
un
numero
variabile
di
macchine
tali
che
possano
essere
aggiunte
o
tolte
a
piacere
a
seconda
del
carico
che
le
applicazioni
portano
alla
struttura
DBMS.
Lo
sharding
può
essere
effettuato
con
vari
meccanismi,
noi
approfondiremo
in
seguito
il
consistent
hashing
che
permette
di
suddividere
i
dati
usando
una
funzione
di
hash
ad
hoc
sulla
chiave
primaria.
Lo
sharding
ha
lo
svantaggio
di
rendere
complesse
le
operazioni
di
join
fra
i
dati,
motivo
per
cui
in
alcuni
NoSql
questo
tipo
di
operazione
non
è
effettuabile
ma
sarà
l’applicativo
eventualmente
a
sopperirvi.
La
replica
più
lo
sharding
creano
un
meccanismo
che
riduce
sia
i
costi
che
i
casi
di
failure
del
sistema,
questi
ultimi
causati
da
macchine
che
si
rendono
improvvisamente
indisponibili
ma
che
non
hanno
più
dati
che
altre
macchine
del
cluster
non
possono
avere.
4. NoSql: Approfondimenti
In
questo
capitolo
approfondiamo
i
meccanismi
usati
dai
database
NoSql
al
fine
di
garantire
le
proprietà
alla
base
di
un
sistema
di
gestione
dei
dati.
4.1. Concorrenza
I
database
NoSql,
invece
di
implementare
sistemi
di
locking,
usano
altri
sistemi
per
la
gestione
della
concorrenza
che
permettono
di
avere
meno
sicurezza
dal
punto
di
vista
della
correttezza
assoluta
dei
dati
ma
una
maggiore
efficienza
a
livello
di
prestazioni
e
tempi
di
risposta
dato
che
vengono
effettuate
molte
più
letture
e
scritture
contemporaneamente.
4.2. Consistenza
Quando
parliamo
di
consistenza
intendiamo
il
recupero
delle
informazioni
tale
che
le
medesime
siano
corrette.
Parliamo
di
stretta
consistenza
nel
caso
in
cui
tutte
le
letture
successive
ad
una
scrittura
debbano
garantire
che
i
dati
siano
tali
a
come
la
scrittura
li
ha
portati
ad
essere;
quindi
o
le
letture
che
seguono
la
scrittura
avvengono
nello
stesso
nodo
o
deve
essere
utilizzato
un
protocollo
distribuito
ad
hoc
(ad
es.
Paxos)
che
permetta
che
si
verifichi
questa
condizione.
Questo
tipo
di
consistenza,
ricordando
il
teorema
di
CAP,
non
può
essere
garantita
assieme
a
disponibilità
e
fault-‐tolerance
dei
dati;
questo
tipo
di
consistenza
presuppone
che
si
rinunci
al
partizionamento
dei
dati
o
alla
disponibilità
costante
dell’informazione.
Parliamo
di
eventual
consistency
invece,
nel
caso
in
cui
le
letture
possano
ritornare
dei
valori
non
aggiornati
all’ultima
scrittura
effettuata
ma,
sicuramente,
il
sistema
prima
o
poi
farò
si
che
questo
valore
venga
correttamente
propagato.
Appartengono
a
questa
categoria
più
tipi
di
consistenza:
• Read
Your
Own
Write
(RYOW)
Consistency
Un
client
che
effettua
una
scrittura
può
vedere
le
letture
successive
già
coerenti
indipendentemente
dal
server
su
cui
la
scrittura
è
stata
fatta
e
le
letture
successive
siano
effettuate.
Questo
non
vale
per
gli
altri
client
che
eseguono
le
letture
successive
alla
scrittura
del
client
in
oggetto.
• Session
Consistency
Simile
alla
RYOW
con
la
differenza
che
le
letture
successive
ad
una
data
scrittura
risultano
corrette
solo
all’interno
di
un
certo
ambito,
ad
esempio
limitatamente
ad
un
nodo.
• Casual
Consistency
Se
un
client
legge
una
versione
1
e
scrive
conseguentemente
una
nuova
versione,
tutti
i
client
che
leggono
la
nuova
versione
proposta
dal
dato
client
allora
leggevano
anche
la
versione
1.
• Monotonic
Read
Consistency
Se
un
dato
client
legge
un
valore
per
una
certa
informazione
allora,
da
questa
lettura
in
poi,
ogni
accesso
di
qualunque
altro
client
su
questa
informazione
non
potrà
leggere
valori
antecedenti.
4.3. Versionamento
Nei
NoSQL
le
tipologie
di
versionamento
che
vengono
implementate
sono
legate
al
fatto
che
le
informazioni
vengono
distribuite
su
più
nodi.
Le
varie
operazioni
di
lettura
e
scrittura
possono
avvenire
su
nodi
diversi
e
non
può
quindi
essere
garantita
una
consistenza
stretta.
Tra
i
vari
sistemi
di
versionamento
adottati,
quelli
che
andremo
a
vedere
più
nel
dettaglio
sono
Vector
Clocks
e
Optimistic
Locking.
4.3.2. Optimistic Locking
Nell’Optimistic
Locking
un
unico
clock
viene
salvato
per
ogni
blocco
di
dati.
Questo
tipo
di
versionamento
è
stato
approfondito
dai
fautori
del
progetto
Project-‐Valdemort
con
la
conclusione
che
in
scenari
distribuiti
dove
le
macchine
vengono
aggiunte
continuamente
ed
altre
disattivate
o
rotte
improvvisamente,
il
sistema
risulta
poco
funzionale.
4.4. Partizionamento
I
sistemi
di
partizionamento
permettono
di
distribuire
le
informazioni
sul
cluster
che
costituisce
il
nostro
database
NoSQL.
Ci
sono
più
tipi
di
partizionamento,
di
seguito
ne
elenchiamo
alcuni:
• Consistent
Hashing
• Memory
Cached
• Clustering
• Separating
Reads
from
Writes
• Sharding
Di
questi,
quelli
normalmente
più
usati
rimangono
consistent
hashing
e
sharding
che
andiamo
a
vedere
più
nel
dettaglio.
Figure 4.1 – Consistent Hashing : Distribuzione dell’informazione in un cluster
Per
capire
come
gli
oggetti
sono
mappati
sui
nodi
basta
seguire
il
giro
dell'orologio
e
si
nota
che
l'oggetto
appartenente
al
nodo
precede
il
nodo
stesso.
Supponiamo
ora
che
un
nodo
abbandoni
il
cluster
per
vari
motivi,
scelta
o
fail-‐over
che
sia.
Avremo
che
l'oggetto
o
gli
oggetti
che
precedono
il
nodo
che
abbandona
lo
schema
andranno
ad
appartenere
al
nodo
direttamente
successivo
ad
esso.
Allo
stesso
modo
se
un
nodo
entra
nel
cluster
allora
gli
oggetti
che
lo
precederanno
andranno
sotto
la
sua
competenza.
Supponiamo
quindi
che
sia
il
nodo
C
ad
abbandonare
lo
schema
e
a
subentrare
sia
un
nodo
D,
avremo
la
seguente
sitazione.
Figure 4 – Consistent Hashing : Ridistribuzione dell’informazione
Quello
che
si
nota
subito
è
che
al
cambiare
dei
nodi
appartenenti
al
cluster
non
tutti
gli
oggetti
debbono
cambiare
nodo
di
appartenenza
ma
soltanto
alcuni
di
essi.
Dalla
distribuzione
che
abbiamo
dato
dei
nodi
nel
cluster
rappresentato
dalla
circonferenza
di
cui
sopra,
possiamo
vedere
che
i
nodi
non
sono
equamente
distribuiti
e
che
quindi
può
essere
che
un
nodo
possa
avere
più
carico
di
un
altro
e
non
essere
bilanciati.
Per
fare
fronte
a
questo
inconveniente
si
è
pensato
di
“inserire”
un
insieme
di
nodi
virtuali
per
ogni
nodo
fisico
presente
nel
cluster.
Il
numero
dei
nodi
virtuali
per
ogni
nodo
fisico
viene
definito
da
parametri
appartenenti
alla
macchina
stessa
(cpu,
memoria,
dimensione
dello
storage)
e
quindi
varia
da
nodo
a
nodo.
Il
consistent
hashing
garantisce
anche
un
sistema
di
replica
basato
su
una
scelta
di
progetto
dove
si
fissa
un
valore
K,
ovvero
un
valore
numerico
che
determina
quante
repliche
devono
essere
mantenute
per
i
dati.
Con
riferimento
alla
figura
appena
sopra,
preso
ad
esempio
K=1,
i
dati
3
e
4
di
competenza
del
nodo
D
saranno
replicati
anche
sul
nodo
successivo,
ovvero
sul
nodo
A.
4.4.2 Sharding
Lo
sharding
è
un
sistema
di
distribuzione
delle
informazioni
effettuato
sui
nodi
appartenenti
al
cluster;
queta
distribuzione
viene
dettata
da
un
processo
iniziale
in
cui
avviene
la
definizione
della
chiave
di
sharding.
Supponiamo
di
avere
10
nodi
su
cui
distribuire
i
dati,
possiamo
pensare
ad
una
chiave
di
sharding
tale
che
il
modulo
della
divisione
per
10
della
chiave
primaria
(numerica)
di
ogni
dato
permetta
di
decidere
dove
posizionare
il
dato.
Questo
sistema
di
distribuzione
dei
dati
viene
usato
ad
esempio
su
MongoDB
e
necessita
di
macchine
dedicate
a
questo
compito
oltre
a
quelle
mantenenti
le
informazioni.
• Riak
• Project
Valdemort
UI
:
1
CF
:
anagrafica
nome
→
Arturo
|
cognome
→
Collodi
|
genere
→
Maschile
|
eta
→
39
CF
:
indirizzo
via
→
Pinocchio
1
|
cap
→
20121
|
città
→
Milano
|
nazione
→
Italia
UI
:
2
CF
:
anagrafica
nome
→
Sara
|
cognome
→
Piccolo
|
genere
→
Femminile
CF
:
indirizzo
via
→
Alfieri
2
|
cap
→
20134
|
città
→
Milano
Figure 5.1 – UI : Unità Informativa; CF : Column-Family;
Con
questo
esempio
riusciamo
a
vedere
la
differenza
che
si
può
avere
tra
una
archiviazione
di
tipo
RDBMS
ed
una
NoSql:
in
questi
ultimi
le
colonne
che
non
sono
valorizzate
non
vengono
riportate,
con
un
notevole
guadagno
di
memoria
rispetto
a
sistemi
relazionali
sui
quali
la
creazione
di
un
campo
nello
schema
significa
predisposizione
al
minimo
spazio
occupabile
di
memoria
o
di
disco:
sui
grandi
numeri
e
con
poche
informazioni
a
disposizione,
il
guadagno
diventa
significativo.
Va
tenuto
in
considerazione
che
l'aggiunta
di
una
colonna
alla
column-‐family,
così
come
l'eliminazione,
non
comporta
una
ridefinizione
dello
schema
e
quindi
è
trasparente
e
immediata;
vediamo
ad
esempio
la
column-‐family
anagrafica
dopo
dei
cambi
di
colonne
presenti
al
suo
interno.
CF
:
anagrafica
UI
:
1
nome
→
Massimo
|
cognome
→
Carro
|
genere
→
Maschile
|
eta
→
39
UI
:
2
nome
→
Sara
|
cognome
→
Piccolo
|
genere
→
Femminile
|
peso
-‐>55
-‐
Aggiunta
della
chiave
hobby
e
eliminazione
del
genere
nell'UI
1
CF
:
anagrafica
UI
:
1
nome
→
Massimo
|
cognome
→
Carro
|
hobby
→
lettura
|
eta
→
39
UI
:
2
nome
→
Sara
|
cognome
→
Piccolo
|
genere
→
Femminile
|
peso
-‐>55
informazioni
solo
per
una
piccola
quantità
di
righe.
Riassumendo,
le
caratteristiche
principali
sono:
• Flessibilità
delle
colonne
appartenenti
ad
una
column-‐family.
• Partizionamento
orizzontale
legato
alla
column-‐family.
Una
data
column-‐family
non
può
essere
“spezzata”
ma
ogni
record
appartenente
ad
essa
può
essere
su
un
server
diverso.
• Uso
di
particolari
file
di
log
per
permettere
un
più
veloce
sistema
di
storage.
• Mancanza
di
un
supporto
transazionale.
Alcuni
esempi
di
implementazioni
in
questa
categoria:
• BigTable
• Cassandra
• HyperBase
5.4. Graph-Oriented
Le
precedenti
tipologie
focalizzano
l’attenzione
sulla
scalabilità
dei
dati
e
sulla
flessibilità
delle
informazioni,
hanno
però
il
problema
di
non
poter
contenere
dati
troppo
connessi.
Da
questa
nuova
esigenza
prende
luce
l’idea
dei
NoSQL
orientati
ai
grafi.
Possiamo
immaginare
questa
categorie
come
una
document
oriented
con
la
clausola
che
i
documenti
sono
anche
adibiti
a
rappresentare
le
relazioni.
Strutture
di
questo
tipo
permettono
il
passaggio
tra
un
nodo
ad
un
altro
(graph
traversal)
e
sono
quindi
molto
utilizzati
nel
campo
del
Social
Network.
Esempi
per
essi
:
• Neo4j
• FlockDb
• Pregel
Alla
fine
di
tutte
queste
analisi,
riassumeremo
i
risultati
in
una
tabella
di
facile
osservazione.
6.1.2. Riak
Riak
è
un
database
Key-‐Value
distribuito
e
decentralizzato
contraddistinto
da
una
struttura
ad
anello,
detta
anche
ring
o
cluster,
che
integra
già
replica
e
sharding.
Ogni
nodo
dell’anello
è
uguale
all’altro
ed
è
lui
stesso
che,
se
“contattato”
da
un
applicativo,
si
fà
carico
di
recuperare
le
informazioni
richieste
ovunque
esse
siano,
ritornandole
al
richiedente.
Questo
processo
avviene
tramite
algoritmi
di
gossiping
che
mantengono
aggiornate
le
informazioni
della
struttura
nel
tempo.
Riak
permette
di
definire
più
strutture
dette
bucket,
che
possono
essere
paragonate
alle
tabelle
nella
logica
SQL,
ma
non
permette
di
creare
più
di
un
database
in
un
singolo
cluster.
6.1.3. Cassandra
Cassandra
è
un
database
Column
Oriented
(detto
anche
Column
Family)
semistrutturato,
ovvero
dotato
di
uno
schema
caratterizzato
da
databases
e
da
Column
Families
(CF),
che
nella
versione
che
analizziamo
assumono
anche
il
nome
di
tabelle;
ogni
CF
può
avere
chiavi
differenti
al
suo
interno
ma
se
esistono
chiavi
uguali
per
tuple
differenti,
allora
le
dette
chiavi
apparterranno
sempre
alla
stessa
Column
Family
(vedi
capitolo
5
:
Column-‐Oriented).
Cassandra
integra
un
meccanismo
di
replica
e
di
sharding.
Lo
sharding
viene
effettuato
per
Column
Family,
ovvero
se
una
chiave
di
una
CF
è
situata
su
una
data
macchina,
allora
lo
saranno
anche
le
altre
chiavi
di
quella
CF
per
la
data
tupla
di
informazioni.
Questa
tipo
di
implementazione
deriva
da
analisi
che
hanno
evidenziato
che,
quando
viene
richiesta
una
informazione
appartenente
ad
una
data
Column
Family,
solitamente
vengono
richieste
anche
le
altre
informazioni
presenti
in
essa.
Per
esempio
una
Column
Family
“indirizzo”
conterrà
chiavi
quali
via,
città,
numero
civico,
ecc…
e
se
recuperiamo
le
informazioni
di
anagrafica
di
un
certo
utente,
alla
voce
“indirizzo”
serviranno
tutte
queste
voci.
Così
facendo,
l’accesso
alla
CF
“indirizzo”
di
una
data
tupla
permette
di
andare
a
recuperare
tutte
le
informazioni
ad
esso
inerenti
sulla
stessa
macchina
e
quindi
di
velocizzare
i
tempi
di
risposta.
In
Cassandra
ogni
nodo
di
un
cluster
è
uguale
agli
altri:
questo
fa
si
che
su
ognuno
di
essi
possano
essere
effettuate
letture
e
scritture.
Da
precisare,
però,
che
all’avvio
del
cluster
alcuni
nodi
hanno
dei
compiti
aggiuntivi;
questi
nodi
prendono
il
nome
di
seeds
ed
è
loro
compito
generare
il
cluster
andando
a
recuperare
tutti
gli
altri
nodi
che
lo
costituiscono.
Una
volta
terminato
questa
fase,
tutti
i
nodi
del
cluster
tornano
ad
avere
le
stesse
caratteristiche.
Cassandra
ha
la
possibilità
di
generare
più
databases
per
ogni
cluster.
6.1.4. Neo4j
Neo4j
è
un
database
Graph
Oriented
che
permette
di
mantenere
sia
i
dati
che
le
relazioni
presenti
tra
questi;
è
simile
ad
un
Document
Oriented
con
la
differenza
che
ogni
documento
può
rappresentare
dati
o
relazioni.b
Neo4j
presenta
una
struttura
Master/Slave
con
la
possibilità
di
effettuare
le
scritture
su
tutti
i
nodi
del
cluster.
Non
è
dotato
di
sharding
e
mantiene
un
unico
grafo
per
ogni
cluster.
configurazione
(Vagrantfile)
ed
appoggiandosi
ad
un
dato
sistema
di
virtualizzazione,
ci
permette
di
creare
quante
macchine
virtuali
desidereremo
su
un
unico
Personal
Computer
che
le
ospita.
La
cosa
che
rende
appetibile
questo
sistema
è
che
aggiungere
o
togliere
una
macchina
virtuale
è
molto
semplice
e
consiste
in
poche
righe
dentro
il
file
di
configurazione
di
Vagrant
stesso.
In
appendice
si
può
trovare
il
file
di
configurazione
usato
per
la
costruzione
di
questo
ambiente.
Nota
Ogni
cluster
verrà
avviato
a
se
stante
per
problemi
di
performance
della
macchina
locale:
quindi
un
cluster
alla
volta.
Il
numero
3
di
MV
è
stato
deciso
tenendo
conto
dei
limiti
che
il
personal
computer
ha
come
RAM,
velocità
di
lettura
disco
e
gestione
risorse
da
distribuire
fra
queste.
Detto
ciò,
lo
schema
di
partenza
per
tutti
i
NoSql
sarà
quindi
rappresentabile
come
segue:
Personal
Computer
Figura 6.2.1: Struttura di analisi cluster NoSql
6.3.1. MongoDB
MongoDB
mette
a
disposizione
dei
repository
ad
hoc
per
l’installazione.
Tramite
yum
è
molto
facile
avere
in
pochi
minuti
una
macchina
stand-‐alone
funzionante,
ci
basta
creare
un
file
/etc/yum.repos.d/mongodb.repo
con
il
seguente
contenuto
e
lanciare
il
comando
che
segue.
[mongodb]
name=MongoDB Repository
baseurl=http://downloads-distro.mongodb.org/repo/redhat/os/x86_64/
gpgcheck=0
enabled=1
Figure 6.3.1 – Contenuto del file : /etc/yum.repos.d/mongodb.repo
bash> sudo yum install mongo-10gen mongo-10gen-server
Figure 6.3.2 - Comandi di installazione per MongoDB
Per
una
configurazione
della
replica
bisogna
lavorare
sia
a
livello
si
configurazione
che
a
livello
di
console
mongo
e
una
volta
che
questa
è
configurata
MongoDB
avrà:
• Creato
di
un
database
local
per
la
gestione
della
replica
(database
non
replicato
ma
presente
su
ognuna
delle
istanze)
e
dimensionato
gli
oplog
(default
5%
del
totale
disco
a
disposizione).
• Allocato
spazio
per
i
files
di
journaling
(default
3
file
da
1GB
l’uno).
Quindi
avendo
a
disposizione
un
disco
di
500GB,
una
istanza
mongod
occupa
circa
28GB.
Per
la
RAM
invece
al
boot
mongod
usa
circa
300MB
e
non
facendo
nessuna
attività,
se
non
tenere
traccia
delle
replica
per
la
gestione
eventuale
del
fail-‐over,
fa
pochissime
letture/scritture
da/su
disco.
I
testi
effettuati
trattano
una
versione
di
MongoDB
2.4.3.
Verificare
quanto
prende
di
disco
per
installare
MongoDB.
6.3.2. Riak
Anche
Riak
come
MongoDB
può
essere
installato
facilmente
tramite
yum.
I
comandi
necessari
sono
i
seguenti:
per
contenere
i
dati
di
circa
5MB
e
sfrutta
una
quantità
di
RAM
pari
a
circa
440M.
Riak
è
scritto
in
Erlang
e
installare
Riak
prende
45MB
disco.
I
test
sono
fatti
con
Riak
1.4.2.
6.3.3. Cassandra
Cassandra
è
un
progetto
open-‐source
Apache
e
si
basa
su
JVM.
Le
nostre
considerazioni
si
basano
su
Cassandra
2.0,
per
la
quale
versione
sono
state
fatte
modifiche
sostanziali
rispetto
le
vecchie
versioni
1.x.
Scaricando
i
binari
e
avendo
già
JVM
installata
si
può
subito
far
partire
una
istanza
di
Cassandra.
bash> wget \
“http://www.apache.org/dyn/closer.cgi?path=/cassandra/2.0.3/apache-
cassandra-2.0.3-bin.tar.gz”
bash> tar zxf apache-cassandra-2.0.3-bin.tar.gz
La
replica
viene
gestita
soltanto
modificando
i
file
di
configurazione
di
ogni
macchina,
una
volta
partite
le
macchine
la
replica
è
funzionante.
Esistono
dei
tool
che
permettono
di
gestire
il
cluster
di
cassandra
da
interfaccia
web,
ad
esempio
Datastax
OpsCenter
o
Helenos.
Una
singola
istanza
in
replica
occupa
circa
200MB
di
RAM
e
1%
di
CPU
quando
parte,
pochissimo
spazio
disco,
400KB.
L’installazione
di
JVM
prende
circa
110MB
di
disco.
I
test
sono
stati
fatti
con
Cassandra
2.0
e
JVM
1.7.
6.3.4. Neo4j
Neo4j
è
un
progetto
di
Neo
Technology
e
si
basa
su
JVM.
Per
poter
funzionare
la
macchina
che
lo
ospita
deve
avere,
oltre
JVM,
anche
il
pacchetto
lsof.
Si
scaricano
direttamente
i
binari
e
metterlo
in
funzione
è
molto
veloce.
Richiede
che
il
numero
di
fie
aperti
sia
almeno
40.000.
http://info.neotechnology.com/download/neo4j_enterprise_1.9.5.tar.gz
tar zxf neo4j_version.tar.gz
Figure 6.3.5 - Comandi di recupero ed installazione di Neo4j
L’esecuzione
iniziale
occupa
10%
di
memoria
e
2.5%
di
CPU.
Neo4j
ha
una
interfaccia
grafica
integrata
che
risponde
sulla
porta
7474
di
default.
I
test
sono
fatti
con
Neo4j
1.9.5
e
JVM
1.7.
6.3.5. Comparazioni
I
grafici
rappresentano
l’occupazione
di
disco,
RAM
e
CPU
nel
momento
in
cui
una
istanza
viene
avviata
e
collegata
al
cluster.
Occupazione
Disco
30
25
Uso
Disco
[GB]
20
MongoDB
15
Riak
10
Cassandra
5 Neo4j
0
Uso
del
disco
[GB]
Database
NoSql
Figure 6.3.5 - Uso del disco : instanza avviata ma nessuna attività verso di essa. La rappresentazione è
molto falsata da MongoDB che occupa qusi 30GB di disco, le altre installazioni sono molto limitate come
occupazione. C’è da dire che questa discrepanza è tale anche per come MongoDB parte di default, nulla
vieta di abbassare lo spazio disco occupato al boot per esso, ma l’esame viene fatto proprio senza sapere
quanto ogni sistema cuba.
300
MongoDB
250
Riak
200
150
Cassandra
100
50
Neo4j
0
RAM
[MB]
NoSql
Database
Figure 6.3.6 - Uso della RAM : instanza avviata ma nessuna attività verso di essa.
Uso
CPU
10%
9%
8%
7%
Uso
CPU
[%]
6%
MongoDb
5%
Riak
4%
3%
Cassandra
2%
Neo4j
1%
0%
CPU
[%]
Database
NoSql
Figure 4.3.7 - Uso della CPU : istanza in piedi ma nessuna attività verso di essa.
Figure 6.3.8 – Informazioni legate al boot di un istanza in un cluster. *tramite pacchetti esterni al tool.
6.4.1. MongoDB
E’
un
database
distribuito
ma
non
decentralizzato,
il
che
significa
che
è
dotato
di
:
• una
macchina
principale
che
chiamiamo
Primary
su
cui
vengono
fatte
le
scritture
e
le
letture
consistenti.
• Altre
macchine,
Secondaries,
per
letture
eventualmente
consistenti
e
su
cui
vengono
replicate
le
informazioni
del
Primary.
Le
configurazioni
più
usate
sono
:
1. Un
Primary
+
N
Secondaries,
fino
ad
un
massimo
di
12
istanze,
incluso
il
Primary;
in
tal
caso
la
gestione
del
failover
è
automatica.
2. Un
Primary
+
N
Secondaries,
fino
ad
un
numero
non
precisato:
questo
è
il
caso
a
cui
degenera
il
precedente
se
il
numero
di
secondaries
supera
le
11
unità;
siamo
in
una
configurazione
classica
Master/Slave,
il
failover
è
da
gestire
a
mano.
3. N
Mongos
+
M
Primary
+
S
Secondaries
(Sharding),
abbiamo
in
questo
caso
un
numero
N
di
macchine
che
si
occupano
di
gestire
lo
sharding
dei
dati
sugli
M
Primary
appartenenri
alle
diverse
catene
ognuna
delle
quali
del
tipo
definito
al
punto
1
od
al
punto
2.
Di
seguito
analizziamo
il
caso
1
ed
il
caso
3;
del
punto
1
vedremo
anche
l’implementazione
tramite
il
nostro
cluster.
Possiamo
rappresentare
la
struttura
che
stiamo
creando
come
segue:
Figure 5.4.2 – Rappresentazione di un cluster Primary – Secondaries con letture eventualmente consistenti.
Come
si
vede
l’applicazione
parla
solo
e
sempre
con
la
macchina
Primary
per
effettuare
le
scritture
e
le
letture
che
devono
garantire
consistenza
dei
dati,
mentre
le
letture
possono
avvenire
dalle
macchine
Secondaries
ma
in
tal
caso
non
abbiamo
la
certezza
che
l’informazione
sia
sempre
consistente
(si
parla
di
letture
eventualmente
consistenti).
Figura 6.4.3 – Sharding con failover per MongoDB : l’applicativo effettua una lettura (od una scrittura) di
una informazione ad una macchina mongos, che si accolla l’onere di verificare dove essa si trova (o dove
andrà scritta), recuperarla (o scriverla) e ritornarla (o comunicare l’avvenuta scrittura) all’applicativo.
L’applicativo non saprà dove le informazioni risiedono ma sarà sempre il layer formato dai server mongos a
far da filtro per accedere alla corretta macchina che mantiene l’informazione desiderata.
6.4.3. Riak
In
Riak
i
concetti
di
Primary/Secondaries
o
Master/Slave
non
esistono,
si
parla
di
ring
o
anello
o
cluster
e
di
nodi
costituenti.
In
Riak
un
nodo
che
appartiene
ad
un
cluster
se
viene
interrogato
può
:
-‐ Fornire
direttamente
le
informazioni
richieste.
Le
informazioni
sono
presenti
sul
nodo.
-‐ Recuperare
le
informazioni
per
poi
rispondere
alla
richiesta.
Le
informazioni
sono
su
un
altro
nodo
e
quindi
vengono
richieste
dal
nodo
contattato
al
nodo
che
le
mantiene.
-‐ Verificare
che
la
richiesta
sia
soddisfatta
e
fornire
le
informazioni
desiderate.
Le
informazioni
devono
essere
garantite
con
un
certo
grado
di
affidabilità
e
quindi
vengono
contattati
più
nodi
che
contengono
le
medesime
e
se
i
dati
sono
coerenti
allora
si
da
una
risposta
positiva
alla
richiesta
(il
concetto
di
“quorum”).
La
prima
cosa
da
notare
è
che
siamo
in
presenza
di
un
sistema
distribuito
e
decentralizzato
dove
non
ci
sono
ulteriori
macchine
se
non
quelle
che
appartengono
al
cluster
e
che
contengono
i
dati.
Sono
queste
macchine
stesse
che
si
occupano
di
recuperare
le
informazioni
richieste,
ovunque
esse
siano
nel
cluster.
E’
chiaro
da
questa
affermazione
che
Riak
fornisce
un
sistema
di
sharding
automatico;
un
vantaggio
notevole
se
si
pensa
che
i
nodi
stessi
che
mantengono
le
informazioni
ridistribuiscono
le
medesime
sopra
di
essi
sapendo
dove
e
come
recuperarle;
vantaggio
che
appare
molto
più
ampio
se
si
pensa
alla
semplicità
della
gestione
all’aggiunta
di
un
nodo
o
alla
fuoriuscita
di
uno
dal
cluster.
Per
sapere
dove
i
dati
si
trovano,
ogni
nodo
usa
un
protocollo
di
gossip:
quest’ultimo
permette
ad
ognuno
di
essi
di
mantenersi
aggiornato
e
di
sapere,
se
contattato
dall’applicativo,
dove
recuperare
i
dati
che
non
ha.
La
replica
viene
gestita
allo
stesso
modo:
saranno
sempre
i
nodi,
tramite
il
meccanismo
di
consistent
hashing,
a
mantenere
automaticamente
il
posizionamento
dei
dati
sui
nodi
del
cluster
ricollocandoli
correttamente
se
uno
o
più
nodi
dovessero
abbandonare
o
venire
aggiunti
all’anello.
La
replica
in
Riak
può
essere
configurata
diversamente
a
livello
di
bucket,
ovvero:
il
numero
di
nodi
su
cui
i
dati
vengono
replicati
può
cambiare
su
ogni
bucket.
Riak
ha
dei
limiti,
tra
cui:
-‐ Non
è
possibile
modificare
la
dimensione
di
un
cluster,
ovvero
il
numero
di
partizioni
che
lo
formano,
a
meno
di
inserire
tutti
i
dati
su
un
nuovo
cluster,
quindi
smantellando
un
cluster
per
uno
nuovo
(il
che
significa
mantenere
due
strutture
fino
a
quando
tutti
i
dati
non
sono
stati
effettivamente
trasferiti).
-‐ Il
cambio
di
metodo
di
archiviazione
dei
dati,
ovvero
il
backend,
non
può
essere
fatto
se
non
reinserendo
i
dati
in
un
nuovo
cluster
con
il
backend
desiderato.
-‐ Il
backend
deve
essere
lo
stesso
per
tutti
i
nodi
del
cluster.
Vediamo
ora
come
Riak
si
adatti
al
nostro
cluster
di
3
istanze.
Lo
spazio
messo
a
disposizione
per
le
chiavi
è
di
2^160-‐bit
di
interi
e
di
default
sono
64
le
partizioni
su
cui
questo
spazio
è
suddiviso.
Avendo
noi
3
nodi
le
partizioni
non
si
distribuiranno
equamente
per
ognuno
di
questi
essendo
il
modulo
di
64/3
=
1.
Quindi
un
nodo
avrà
una
partizione
in
più.
Nodo 1 : 22 partizioni
Nodo 2 : 21 partizioni
Nodo 3 : 21 partizioni
Figure 6.4.4 – Distribuzione delle partizioni tra i nodi
In
Riak,
però,
si
parla
di
nodi
virtuali
(vnodes),
quindi
supponendo
di
avere
3
nodi
virtuali
per
ogni
nodo
si
avrà,
ad
esempio,
per
il
nodo
1:
Nodo 1 : 22 partizioni
VNode1 : 8 partizioni
VNode2 : 7 partizioni
VNode3 : 7 partizioni
Figure 6.4.5 – Distribuzione delle partizione tra nodi virtuali su un singolo nodo
e
così
via
per
gli
altri.
Graficamente
possiamo
meglio
vedere
questa
distribuzione.
Rappresentiamo
un
cluster
di
24
partizioni
per
comodità
di
visualizzazione
Figure 6.4.6 – Cluster Riak : distribuzione dell’informazione
I
dati
vengono
distribuiti
lungo
le
partizioni
in
maniera
equa
usando
un
meccanismo
di
consistent
hashing
che
codifica
bucket
+
chiave
e
trova
la
partizione
che
deve
contenere
il
dato
o
da
cui
recuperare
il
dato.
Il
nostro
cluster
in
Riak
è
formato
dalle
3
macchine
virtuali
che
formano
l’anello:
bash> riak-admin status | grep members
ring_members : ['[email protected]','[email protected]',
'[email protected]']
Figure 6.4.7 - Verifica anello Riak
6.4.4. Cassandra
Anche
per
Cassandra
non
esiste
il
concetto
di
master,
ogni
nodo
del
cluster
è
uguale
agli
altri
fatta
eccezione
alcuni
fra
essi
a
cui
viene
dato
il
ruolo
di
seeds.
Questi
ultimi
devono
essere
fatti
partire
prima
di
tutti
gli
altri
che
costituiranno
il
cluster
ed
hanno
il
compito
di
trovare
i
nodi
mancanti
e
completare
l’anello.
Fatta
questa
premessa,
una
volta
che
l’anello
è
in
piedi
ogni
nodo
è
uguale
all’altro;
quando
viene
fatta
una
richiesta
ad
un
nodo
è
il
medesimo
che
sa
dove
recuperare
le
informazioni
richieste
o
dove
memorizzare
quelle
inviate.
Cassandra
garantisce
scalabilità
orizzontale
e
lineare,
il
che
permette
di
aggiungere
o
togliere
nodi
al
cluster
di
partenza
sia
per
estendere
che
per
migliorare
le
prestazioni
del
cluster:
questa
operazione
può
essere
fatta
a
caldo,
senza
restartare
il
cluster.c
c
Con
scalabilità
lineare
intendiamo
che
se
due
nodi
possono
sostenere
100.000
transazioni
al
secondo,
4
ne
potranno
sostenere
fino
a
200.000
e
8
fino
a
400.000.[12]
I
file
di
configurazione
di
Cassandra
vengono
scritti
di
default
con
yalm
che
ha
la
caratteristica
di
essere
molto
di
più
facile
lettura
che
xml.
Nel
nostro
caso
tutti
sono
dei
nodi
seeds,
quindi
dopo
aver
configurato
correttamente
la
replica
nei
vari
file
di
configurazione
possiamo
vedere
lo
stato
della
stessa
con
il
comando
nodetool
a
disposizione
tra
i
comandi
bash
di
Cassandra.
A
differenza
di
MongoDB
e
Riak,
la
replica
in
Cassandra
viene
configurata
esclusivamente
nel
file
di
configurazione
ed
allo
start
le
macchine
si
“cercano”
e
trovano
senza
fare
nient’altro.
Di
seguito
i
parametri
di
configurazione
base
cluster
(ad
esempio
per
il
nodo
192.168.56.223)
e
il
recupero
dello
stato
del
cluster
una
volta
avviato.
cluster_name: 'MyCluster'
num_tokens: 256
seed_provider:
- class_name: org.apache.cassandra.locator.SimpleSeedProvider
- parameters:
- seeds: "192.168.56.223, 192.168.56.224, 192.168.56.223"
listen_address: 192.168.56.223
rpc_address: 0.0.0.0
endpoint_snitch: RackInferringSnitch
Figure 6.4.8 – Spaccato di un file di configurazione per un singolo nodo per generare un cluster
Figure 6.4.9 - Stato del cluster, istanze in replica e sharding dei dati.
6.4.5. Neo4j
In
Neo4j
torniamo
ad
una
struttura
Master/Slave
senza
la
possibilità
di
avere
sharding
dei
dati:
il
Master,
come
tutti
gli
Slave
in
replica,
conterrà
tutti
i
dati
appartenenti
all'intero
grafo.
Vediamo
di
seguito
i
parametri
principali
per
garantire
HA
nel
nostro
solito
cluster
di
macchine
virtuali.
I
file
da
configurare
sono
i
seguenti:
• conf/neo4j.properties
• conf/neo4j-‐server.properties
ed
i
parametri
per
garantire
una
replica:
• ha.server_id
identificativo
univoco
per
ogni
istanza
appartenente
al
cluster.
• ha.initial_hosts
ip
e
porta
per
ogni
host
appartenente
al
cluster.
• org.neo4j.server.webserver.address
indirizzo
ip
di
risposta
del
webserver,
0.0.0.0
permette
a
chiunque
l’accesso.
org.neo4j.server.database.mode
abilita/disabilita
meccanismo
di
HA
Una
volta
configurati
questi
parametri,
avviando
le
istanze,
null’altro
verrà
chiesto
per
rendere
disponibile
la
replica.
Vediamo
di
seguito
la
configurazione
di
un
macchina
del
nostro
cluster.
ha.server_id = 1
ha.initial_hosts = 192.168.56.223:5001,
192.168.56.224:5001,
192.168.56.225:5001
Figure 6.4.10 - neo4j.properties : spaccato per la creazione di un cluster
org.neo4j.server.webserver.address = 0.0.0.0
org.neo4j.server.database.mode = HA
Figure 6.4.12 - HA dal master : il parametro InstancesInCluster mantiene le informazioni per tutte le istanze
appartenenti al cluster.
Nota
Solo
per
MongoDB
servirebbe
una
ulteriore
analisi
e
caricamento
massivo
per
un
ambiente
in
sharding
tra
2
macchine
mongos
e
6
mongod
(figura
N.
X)
ma
caricare
dati
su
8
macchine
virtuali
su
uno
stesso
host
ospitante
farebbe
decadere
le
prestazioni,
quindi
omettiamo
in
questo
ambito
questa
analisi.
6.5.1. MongoDB
6.5.1.1. Accesso alla console e generazione dei dati
MongoDB
è
dotato
di
una
console
accessibile
via
bash
tramite
il
comando
mongo
che
permette
di
interrogare
i
database
storati
ed
i
loro
contenuti
grazie
a
funzioni
javascript
create
ad
hoc.
bash# mongo
MongoDB shell version: 2.4.3
set0:PRIMARY>
Figure 6.5.1 – Connessione alla console
Vediamo
anzitutto
come
interrogare
una
macchina
mongod
nel
nostro
cluster.
Solo
una
macchina
alla
volta
può
essere
Primary
indipendentemente
dalla
configurazione
prescelta;
tutte
le
altre
sono
Secondaries.
Questo
evidenzia
il
fatto
che
una
macchina
avrà
possibilità
di
read/write
consistenti
(il
Primary)
mentre
le
altre
permetteranno
solo
read
eventualmente
consistenti
(le
Secondaries).
Nel
nostro
cluster,
senza
macchine
mongos,
per
effettuare
un
inserimento
di
una
informazione
da
console,
dobbiamo
prima
accertarci
di
quale
sia
la
macchina
Primary;
il
comando
che
ci
permette
di
farlo
è
il
seguente:
set0:SECONDARY> db.isMaster().primary
192.168.56.223:27017
Che
ci
ritorna
IP
e
PORTA
del
Primary;
a
questo
punto
ci
basta
salire
sulla
macchina
identificata
ed
effettuare
le
scritture
desiderate.
mypc> ssh 192.168.56.223
bash# mongo
MongoDB shell version: 2.4.3
set0:PRIMARY>
6.5.3.2. Accesso ai dati
Con
riferimento
all’esempio
riportato
in
Appendice
B,
genereremo
un
nuovo
database:
automobili
e
raccoglieremo
le
informazioni
in
due
collections
:
autovetture
e
produttori,
dalle
quali
poi
andremo
a
recuperare
i
dati
desiderati.
La
creazione
di
una
collection
avviene
automaticamente
introducendo
dati
in
essa.
Il
codice
nella
figura
6.5.4
rappresenta
la
situazione
dopo
gli
inserimenti,
che
sono
proposti
in
Appendice;
qui
visualizziamo
i
comandi
per
vedere
database
e
collections
per
esso.
set0:PRIMARY> db.autovetture.find({'modello':'Punto'})
{ "_id" : 1, "marca" : "Fiat", "modello" : "Punto", "tipologia" :
"Utilitaria", "alimentazione" : "Benzina", "cilindrata" : "1400", "prezzo" :
10 }
{ "_id" : 2, "marca" : "Fiat", "modello" : "Punto", "tipologia" :
"Utilitaria", "alimentazione" : "GPL", "cilindrata" : "1200", "prezzo" : 12 }
Join di informazioni
La
join
in
MongoDB
non
è
supportata,
serve
quindi
normalizzare
i
dati
duplicando
le
informazioni
nelle
collections
che
si
vorrebbero
unire.
Nel
nostro
caso
il
campo
marca
ci
permette
di
sapere,
data
una
autovettura,
dove
ha
sede
il
produttore
dell’autovettura
stessa
tramite
due
separate
queries.
set0:PRIMARY> db.autovetture.find({'modello':'Punto','alimentazione':'GPL'})
{ "_id" : 2, "marca" : "Fiat", "modello" : "Punto", "tipologia" :
"Utilitaria", "alimentazione" : "GPL", "cilindrata" : "1200", "prezzo" : 12 }
set0:PRIMARY> db.produttori.find({'marca':'Fiat'},{'marca':1,'citta':1})
{ "_id" : 1, "marca" : "Fiat", "citta" : "Torino" }
6.5.1.3. Inserimento massivo
Per
verificare
i
tempi
di
inserimento
di
informazioni
tramite
un
caricamento
massivo
dei
dati
usiamo
pymongo,
un
driver
Python
per
MongoDB.
I
tempi
di
caricamento
saranno
osservati
con
uno,
dieci
o
venti
thread
contemporanei.
Durante
il
caricamento
la
CPU
è
spesso
al
100%,
la
RAM
va
al
75%
mentre
l’IO
varia
con
picchi
che
raggiungono
il
95%
di
carico.
Di
seguito
la
tabella
con
tutti
gli
esperimenti
riportati.
1200 1221
1000
200
121
53
47
0
12
5
1
Thread
Singolo
[sec.]
10
Threads
[sec.]
20
Thread
[sec.]
Figure 6.5.8 - Inserimento dati al cambio del numero di threads - MongoDB
Si
può
notare
come
l’aumento
di
threads
incida
notevolmente
sulla
velocità
di
inserimento
delle
informazioni,
purtroppo
però
MongoDB,
avendo
solo
n
Primary
su
cui
effettuare
gli
inserimenti,
non
può
scalare
orizzontalmente
(ricordiamo
che
stiamo
analizzando
il
caso
di
cluster
con
3
nodi
senza
sharding).
6.5.2. Riak
6.5.2.1. Accesso alla console e generazione dei dati
Per
accedere
ai
dati
Riak
usa
una
console
Erlang,
quindi
le
query
da
console
vengono
fatte
tramite
questo
linguaggio.
Riak,
nel
nostro
cluster,
gira
in
background,
quindi
per
accedere
alla
console
useremo
il
comando
riak-‐attach.
bash> riak-attach
Remote Shell: Use "Ctrl-C a" to quit. q() or init:stop() will terminate the
riak node.
Erlang R15B01 (erts-5.9.1) [source] [64-bit] [async-threads:0] [kernel-
poll:false]
Un
esempio
di
chiamata
Solr-‐like
per
recuperare
tutti
i
modelli
“Punto”
tra
tutti
i
documenti
può
essere
vista
in
figura
6.5.10,
dove
vengono
mostrati
anche
i
risultati.
bash> curl \
"http://192.168.56.223:8098/solr/autovetture/select?start=0&rows=10& /
q=’modello:Punto&fl=marca,modello,alimentazione"
<xml>
<doc id=1>
<marca>Fiat</marca>
<modello>Punto</modello>
<alimentazione>Benzina</alimentazione>
</doc>
<doc id=2>
<marca>Fiat</marca>
<modello>Punto</modello>
<alimentazione>Benzina</alimentazione>
</doc>
Raggruppamento di informazioni
In
Riak
per
aggregare
le
informazioni
si
utilizza
il
paradigma
di
Map-‐Reduce.
50000 50000
40000
10000
insert
30000
100000
insert
6.5.3. Cassandra
6.5.3.1. Accesso alla console e generazione dei dati
Alla
console
di
Cassandra
2.0
si
accede
tramite
il
comando
cql,
acronimo
di
Cassandra
Query
Language,
linguaggio
di
interrogazione
del
DBMS.
Supposto
che
i
binari
di
Cassandra
si
trovino
nella
directory
/usr/local/cassandra,
vediamo
come
accedere
alla
console.
bash> cd /usr/local/cassandra
bash> ./bin/cqlsh
Connected to My Cluster at localhost:9160.
[cqlsh 4.1.0 | Cassandra 2.0.2 | CQL spec 3.1.1 | Thrift protocol 19.38.0]
Use HELP for help.
cqlsh>
Nota
In
Cassandra
la
creazione
di
un
nuovo
keyspace
è
statica,
ovvero
il
database
esiste
anche
se
non
ci
sono
ancora
dati
archiviati
in
esso.
Il
nostro
keyspace,
inerente
all’esempio
che
si
trova
in
Appendice
B,
viene
creato
definendo
una
motodologia
di
replica
ed
un
fattore
di
replica,
ovvero
il
tipo
di
replica
che
si
desidera
con
il
numero
di
repliche
che
si
desidera
avere
per
i
dati.
si
può
vedere
guardando
la
creazione
della
tabella
autovetture
in
figura
6.5.15.
Ecco
quindi
come
creare
l’indice
sul
campo
tipologia.
Figure 6.5.16 - Creazione di un ulteriore indice
Ora
che
abbiamo
l’indice
possiamo
interrogare
la
base
di
dati
e
vedere
tornare
i
risultati
aspettati
(figura
6.5.17).
cqlsh> SELECT * FROM automobili.infobase WHERE tipologia='Utilitaria';
modello | marca | motore | tipologia
---------+------------+----------------+------------
Punto | Fiat | Benzina | Utilitaria
Punto | Fiat | GPL | Utilitaria
A1 | Audi | Benzina | Utilitaria
Clio | Renault | Benzina | Utilitaria
Figure 6.5.17 – Elenco delle utilitarie tra le autovetture
Raggruppamento di informazioni
Fare
un
GROUP
BY
in
gergo
MySQL
non
è
possibile
con
Cassandra,
dobbiamo
quindi
percorrere
una
strada
più
onerosa.
Creiamo
un
altro
indice
per
la
marca
e
per
ogni
marca
vediamo
il
numero
di
utilitarie
che
hanno.
6.5.3.4. Bulk Insert
Andiamo
ora
ad
effettuare
delle
prove
di
carico
tenuto
presente
che
il
fattore
di
replica
è
pari
al
numero
di
nodi
massimo
che
stiamo
usando,
3.
Durante
il
caricamento
a
singolo
thread
si
può
vedere
sulla
macchina
un
carico
si
CPU
pari
al
99.9%,
mentre
per
quanto
riguarda
la
RAM
siamo
attestati
al
70%
e
IO
molto
basso,
2%,
con
punte
a
30%
ma
con
macchine
virtuali
sopra
una
macchina
fisica
difficile
fare
una
valutazione
se
picchi
dovuti
a
questo
inserimento
o
della
macchina
fisica
stessa
per
altri
processi
in
esecuzione.
6.5.4. Neo4j
6.5.4.1. Accesso alla console e generazione dei dati
Neo4j
usa
Cypher
(cql
:
Cypher
Query
Language)
come
linguaggio
per
inserire
o
cercare
informazioni
tramite
console;
quindi,
supposto
che
Neo4j
sia
stato
installato
in
/usr/local/neo4j,
avremo:
bash> cd /usr/local/neo4j
bash> ./bin/neo4j-shell
Welcome to the Neo4j Shell! Enter 'help' for a list of commands
NOTE: Remote Neo4j graph database service 'shell' at port 1337
neo4j-sh (0)$
Figure 6.5.20 – Accesso alla console di Neo4j.
6.5.4.2. Accesso ai dati
Vediamo
ora
come
inserire
i
nostri
dati
di
test
relativi
al
solito
esempio
di
Appendice
B.
In
Neo4j
la
gestione
delle
informazioni
è
piatta,
quindi
non
si
possono
creare
più
database
o
keyspace,
tutti
gli
elementi
sono
nodi
o
relazioni
corredati
da
proprietà.
Nel
caso
che
stiamo
analizzando
riportiamo
un
grafico
ulteriore
a
sottolineare
come
le
informazioni
siano
interconnesse
evidenziando
i
dati
intesi
come
nodi
e
i
dati
intesi
come
relazioni
fra
di
essi.
Figure 6.5.21 - Grafo interconnessioni nodi e relazioni.
Nella
foto
i
nodi
sono
evidenziati
con
dei
tondi
e,
a
seconda
della
categoria,
con
colori
differenti.
Le
relazioni
invece
sono
frecce
che,
in
questo
caso,
definiscono
una
“appartenenza”;
in
questo
esempio
che
la
marca
“Fiat”
ha
un
modello
che
si
chiama
“Punto”
che
può
avere
un
motore
a
“Metano”
o
a
“GPL”
o
“Diesel”
o
a
“Benzina”.
Fatto
l’inserimento,
che
possiamo
trovare
sempre
in
Appendice,
per
vedere
l’elenco
di
informazioni,
suddividendo
autovetture
e
produttori,
eseguiamo
le
query
riportate
nelle
prossime
due
figure.
Figure 6.5.22 - Elenco delle autovetture inserite visualizzate marca, modello, alimentazione e prezzo
Vediamo
di
seguito
un
filtro
sul
costo
autovetture
tale
che
sia
minore
di
una
certa
soglia.
Join di informazioni
Neo4j
permette
di
relazionare
le
informazioni
inserendo
appropriatamente
le
relazioni
tra
di
esse,
Questo
permette
di
esplicitare
la
relazione,
non
dovere
normalizzare
le
informazioni
e
quindi
non
avere
delle
duplicazioni.
Vediamo
come
inserire
una
relazione,
ad
esempio
che
“Fiat”
fa
le
“Punto”.
neo4j-sh (0)$ start n = node(1002) match (n)--(x) return
n.marca,n.citta,x.modello,x.alimentazione;
+--------------------------------------------------+
| n.marca | n.citta | x.modello | x.alimentazione |
+--------------------------------------------------+
| "Fiat" | "Torino" | "Punto" | "Benzina" |
| "Fiat" | "Torino" | "Punto" | "GPL" |
+--------------------------------------------------+
6.5.4.3. Bulk Insert
7000 6840
6000
5400
5400
5000
1000000
insert
4000
10000
insert
3000
100000
insert
2000
668
680
956
1000
540
68
76
132
0
0
0
MonoThread
10
Threads
20
Threads
20
Threads
3
server
Figure 6.5.26 – Inserimento dati tramite numero di thread variabile. Neo4j
Analizzando
i
dati
si
osserva
che
il
caricamento
tramite
mono
thread
passando
verso
una
sola
macchina
quindi,
è
lineare
e
se
per
inserire
10000
nodi
ci
vogliono
9
minuti,
per
inserirne
100000
ce
ne
vogliono
90
di
minuti:
possiamo
quindi
stimare
che
per
inserirne
un
milione
ci
servono
900
minuti
ovvero
15
ore.d
Se
usiamo
10
threads,
sempre
passando
da
un
solo
server
per
effettuare
l’inserimento,
servono
68
secondi
per
fare
10000
insert
e
670
circa
per
farne
100000.
Circa
gli
stessi
dati
anche
se
poco
peggiori
per
20
threads.
Proseguendo
vediamo
una
quarta
voce
nel
grafico,
ovvero
la
distribuzione
dei
20
thread
sulle
3
macchine
in
maniera
bilanciata:
-‐ 7
sul
primo
server
-‐ 7
sul
secondo
server
-‐ 6
sul
terzo
server
Questa
misurazione
è
importante
in
quanto
Neo4j,
anche
se
ha
una
struttura
Master/Slave,
permette
che
le
scritture
avvengano
su
tutte
le
macchine
e
non
su
una
soltanto
(a
differenza
ad
esempio
di
MongoDB).
Salta
all’occhio
che
non
si
ha
un
vantaggio
per
la
velocità
di
inserimento
ma
chiaramente
abbiamo
la
possibilità
di
scalare
e
distribuire
il
carico
in
maniera
più
equilibrata.
In
questo
caso
però
i
dati
di
replica
che
viaggiano
sulla
rete
sono
più
bassi
del
33%
circa
(avendo
un
caricamento
bilanciato
sulle
macchine
e
quindi
dovendo
ogni
macchina
ricevere
le
parti
mancanti);
le
macchine
si
riallinieranno
un
po’
più
velocemente
del
caso
del
caricamento
massivo
su
una
sola
macchina:
ciò
significa
avere
una
consistenza
dei
dati
più
rapida
ma
da
contraltare
il
d
Quest’ultimo
valore
non
è
riportato
graficamente
per
non
“schiacciare”
le
altre
informazioni
che
ci
interessano
maggiormente.
fatto
che
i
dati
mentre
si
inseriscono
non
saranno
su
nessun
server
consistenti
(avendo
distribuito
il
carico
e
quindi
non
essendoci
un
singolo
server
di
scrittura).
I
dati
sono
copiati
interamente
sulle
altre
macchine
quindi
non
c’è
uno
sharding
ma
ogni
macchina
che
appartiene
al
cluster
mantiene
tutti
i
dati.
7. Conclusioni
Dai
dati
che
abbiamo
sopra
esposto,
possiamo
affermare
che
i
database
NoSQL
non
vengono
scelti
in
base
al
gusto
personale
ma
in
base
alle
caratteristiche
che
devono
avere.
Ad
esempio,
i
sistemi
con
sharding
non
automatico,
vedi
ad
esempio
MongoDB,
fanno
si
che
sia
l’utente
o
comunque
l’applicativo
a
ridistribuire
il
carico
delle
informazioni
tra
i
servers
che
costituiscono
l’ambiente.
Questo
è
un
compito
tedioso
e
difficile
che
può
portare
ad
analisi
molto
approfondite
soprattutto
se
i
dati
cambiano
continuamente
nel
database.
Per
questo
motivo
sono
da
preferirsi,
nel
caso
si
voglia
effettuare
uno
sharding,
i
sistemi
che
lo
integrano
automatico
e
che
solitamente
usano
il
sistema
di
consistent
hashing:
tra
i
nostri
NoSQL
con
questa
caratteristica
troviamo
Riak
e
Cassandra,
mentre
Neo4j
non
è
neanche
da
tenersi
in
considerazione
non
supportando
la
distribuzione
tra
i
nodi.
D’altra
parte
MongoDB
è
molto
più
veloce
dei
diretti
concorrenti
e
permette
di
effettuare
molte
tipologie
di
queries
sui
dati
grazie
all’implementazione
di
parecchi
indici
di
ricerca
e
alla
struttura
di
journaling.
Un'altra
caratteristica
che
salta
all’occhio
è
che
MongoDB,
come
Cassandra,
sono
NoSQL
multi
databases,
quindi
nel
caso
di
sharding
per
più
database
sono
da
preferirsi
a
Riak
e
Neo4j.
Altro
fattore
molto
importante
è
verificare
se
il
DBMS
NoSQL
sia
distribuito
e
decentralizzato.
MongoDB
è
distribuito
ma,
avendo
un
legame
1:1
tra
inserimento
informazione
e
Primary,
non
può
certo
dirsi
decentralizzato,
caratteristica
che
hanno
in
comune
gli
altri
NoSQL
esamitati.
Cassandra
è
consigliato
inoltre
per
sistemi
che
scalano
orizzontalmente,
ovvero
per
sistemi
per
i
quali
si
chiede
l’aggiunta
di
nodi
continuamente,
e
che
necessitano
di
ampliare
lo
spazio
di
memorizzazione
dell’informazione
nel
tempo;
inoltre
la
sua
suddivizione
per
tipologia
delle
informazioni
permette
di
avere
un
migliore
accesso
a
sistemi
che
necessitano
recuperi
di
informazione
omogenea.
Schematicamente.
MongoDB
PRO
• Usa
molto
disco
ma
è
molto
performante.
• Da
usare
per
caricamenti
continui
e
veloci
e
se
sono
da
gestire
più
di
un
database.
• Lo
sharding
permette
di
splittare
i
dati
ma
più
copie
degli
stessi
dati
appartengono
sempre
e
comunque
a
ad
un
sottoinsieme
Primary/Secondaries
esclusivo.
• Failover
garantito.
• Ha
macchine
specifiche
che
si
occupano
di
fare
lo
sharding.
CONTRO
• Degenera
su
sistema
Master/Slave
per
catene
di
più
di
12
istanze.
• Lo
sharding
mantiene
le
copie
di
dati
sulle
singole
catene
Primary/Secondaries.
• Per
realizzare
un
primo
sharding
servono
almeno
8
istanze.
• La
replica
dei
dati
è
uguale
per
tutti
i
database
del
sistema
a
meno
di
accorgimenti
ad
hoc
su
ogni
macchina
Secondaries.
Riak
PRO
• Distribuito
e
decentralizzato
• Ogni
macchina
è
uguale
alle
altre.
• Ogni
macchina
puà
ricevere
letture
e
scritture.
• Replica
configurabile
per
ogni
bucket
per
quanto
concerne
il
numero
di
nodi
che
mantengono
i
dati.
• Da
usare
se
si
desidera
scalare
orizzontalmente
e
se
accesso
ai
dati
è
prioritario
via
chiave.
CONTRO
• Lento.
• Queries
di
accessi
ai
dati
limitate.
Cassandra
PRO
• Performante.
• A
regime
i
nodi
sono
tutti
uguali.
• Ogni
macchina
puà
ricevere
letture
e
scritture.
• Da
usare
per
scalare
orizzontalmente
e
se
serve
ridimensionare/ampliare
velocemente
il
cluster.
CONTRO
• I
nodi
inizialmente
non
sono
tutti
uguali,
alcuni
servono
per
contattare
gli
altri
e
costruire
il
cluster,
va
tenuto
in
considerazione
in
fase
di
start
del
cluster.
• Schema
da
definire.
• Column-‐Families
da
definire.
Neo4j
PRO
• Sistema
Master/Slave
• Definisce
dati
e
relazioni
entrambi
come
documenti.
• Ogni
macchina
puà
ricevere
letture
e
scritture.
• Permette
join
tra
dati
grazie
alle
relazione
esplicitate
e
permette
di
evitare
Map-‐Reduce.
• L’accesso
ai
dati
avviene
tramite
linguaggi
basati
su
query
quali
Gremlin
e
Cypher;
quest’ultimo
garantisce
la
transazionalità
delle
operazioni
e
le
proprietà
acide
delle
stesse.
CONTRO
• Non
permette
sharding.
• Lento.
8. Glossary
Bitcask
E’
una
applicazione
Erlang
che
fornisce
API
per
memorizzare
o
recuperare
informazioni
sotto
forma
di
Key-‐Value
in
una
hash-‐table
LSF
(Log-‐Structured
File-‐system)
che
permette
scritture
ed
accessi
molto
rapidi.
CRUD
Create,
Read,
Update,
Delete
:
sono
le
operazioni
di
base
di
sistemi
Key-‐Value.
Data Model
E'
un
modello
astratto
che
permette
di
documentare
ed
organizzare,
tramite
testo
e
simboli,
i
dati
o
meglio
l'informazione.
[Hoberman]
Erlang
Linguaggio
nato
per
ottimizzare
disponibilità
del’informazione,
concorrenza
e
tolleranza
ai
gusti.
Gossip
Protocollo
di
comunicazione
peer-‐to-‐peer
per
scoprire
e
condividere
informazioni
di
varia
natura
sui
vari
nodi
che
compongono
il
cluster.
Le
informazioni
sono
subito
disponibili
localmente
su
ogni
nodo
in
modo
da
poter
essere
usate
immediatamente
al
proprio
restart.[12]
HDFS
Distributed
File-‐System
used
by
Hbase.
Horizontal Partitioning - Sharding
Memorizzazione
di
record
di
informazione
su
diverse
macchine
in
base
ad
una
data
chiave.
Horizontal Scaling – Scale out (Scalabilità Orizzontale)
La
capacità
di
distribuire
su
più
macchine
sia
i
dati
che
il
carico
delle
operazioni
per
accedere,
modificare
e
memorizzare
gli
stessi.
Tutto
questo
senza
che
le
macchine
condividano
ne'
RAM
ne'
disco.
JSON (Java Script Object Notation)
Formato
adatto
allo
scambio
dati
client-‐server
usato
molto
per
la
semplicità
della
propria
rappresentazione.
MVCC (Multi-Versioning Cuncurrency Control)
bla
bla
bla
bla....
OLTP
It's
a
metodology
to
provide
end
user
to
access
large
amounts
of
data
in
rapid
manner.
Systems
that
facilitate
and
manage
transaction-‐oriented
applications.
Is's
used
to
refer
to
OLTP
as
the
processing
in
which
the
system
responds
immediately
to
user
requests,
like
Automatic
Teller
Machine
of
a
Bank
(ATM).
OPLOG [MongoDB]
Abbreviazione
di
OPeration
LOG,
è
uno
spazio
usato
per
mantenere
le
informazioni
delle
operazioni
che
hanno
modificato
i
dati
memorizzati
nel
database.
Il
file
viene
scritto
da
una
macchina
Primary
e
messo
a
disposizione
delle
macchine
Secondaries
che,
leggendolo,
aggiornano
in
modo
asincrono
le
modifiche
che
si
sono
attuate
sul
Primary.
Si
può
vedere
come
lo
strumento
in
grado
di
mantenere
le
repliche
eventualmente
consistenti
nel
tempo.
Partizionamento Verticale
Parte
di
un
singolo
record
viene
memorizzato
su
server
diversi.
Paxos
Definizione
di
Paxos.
Scalabilità Orizzontale
Possiamo
vederla
come
la
possibilità
di
migliorare
le
performance
di
un
sistema
aumentando
il
numero
delle
macchine
che
esso
ha
a
disposizione.
L’aggiunta
continua
di
machine
permette
di
avere
le
stesse
non
troppo
costose
e
di
facile
reperibilità
sul
mercato.
Scalabilità Verticale (Vertical Scaling, Scale up)
Ovvero
il
potenziamento
del
sistema
dato
dal
potenziamento
della
macchina
atto
a
mantenerlo:
vengono
quindi
aumentate
il
numero
di
CPU
oltre
che
RAM
e
disco.
Chiaramente
questa
scalabilità,
tipica
dei
RDBMS
fa
lievitare
i
costi
dell’hardware.
Thrift
E’
un
framework
dotato
di
un
motore
per
la
generazione
di
codice
al
fine
di
costrire
servizi
per
i
maggiori
linguaggi
di
programmazione[18].
Yum - Yellow dog Updater Modified
E’
il
sistema
di
aggiornamento
ufficiale
per
Fedora,
affianca
rpm,
si
appoggia
a
repository
esterni
per
scaricare
o
aggiornare
software
sul
sistema.
La
caratteristica
principale
di
yum
è
quella
di
risolvere
autonomamente
le
dipendenze
necessarie
per
far
si
che
i
software
da
scaricare
funzionino
correttamente.
9. References
[1] Amazon. http://it.wikipedia.org/wiki/Amazon.com - [Wikipedia]
[4] Fay Chang, Jeffrey Dean, Sanjay Ghemawat, Wilson C. Hsieh, Deborah A. Wallach,
Michael Burrows, Tushar Chandra, Andrew Fikes, Robert E. Gruber: Bigtable: A
Distributed Storage System for Structured Data. ACM Trans. Comput. Syst. 26(2) (2008)
[5] Avrilia Floratou, Nikhil Teletia, David J. DeWitt, Jignesh M. Patel, Donghui Zhang:
Can the Elephants Handle the NoSQL Onslaught? PVLDB 5(12): 1712-1723 (2012)
[11] Comparative Study of the New Generation, Agile, Scalable, High Performance
NOSQL Databases. Clarence J M Tauro, Aravindh S, Shreeharsha A.B –
[Internation Journal of Computer Application]
[17] Web Caching with Consistent Hashing. David Karger, Alex Sherman - [MIT
Laboratories]
[19] VirtualBox, Technical Documentation.
https://www.virtualbox.org/wiki/Technical_documentation - [Oracle]
[21] A. Calì, D. Martinenghi, and D. Carbotta. Query optimisation for web data sources:
minimisation of the number of accesses (Extended Abstract). In Proceedings of the Fif-
teenth Italian Symposium on Advanced Database Systems, SEBD 2007, 17-20 June 2007,
Torre Canne, Fasano, BR, Italy, pages 316–323, 2007.
[22] P. Chen. The Entity-Relationship model: Toward a unified view of data. ACM Trans.
Database Syst., 1(1):9–36, Mar. 1976.
[25] H. Christiansen and D. Martinenghi. Simplification of integrity constraints for data in-
tegration. In Foundations of Information and Knowledge Systems, Third International Sym-
posium, FoIKS 2004, Wilhelminenburg Castle, Austria, February 17-20, 2004, Proceedings,
volume 2942 of Lecture Notes in Computer Science, pages 31–48. Springer, 2004.
[28] H. Christiansen and D. Martinenghi. On using simplification and correction tables for
integrity maintenance in integrated databases. In Proceedings of the Second International
Workshop on Logical Aspects and Applications of Integrity Constraints (LAAIC06) 8 Sep-
tember 2006, Krakow, Poland, pages 569–576. IEEE Computer Society, 2006.
[29] H. Decker and D. Martinenghi. Avenues to flexible data integrity checking. In Pro-
ceedings of the International Workshop on Flexible Database and Information System
Technology (FlexDBIST-06) 6 September 2006, Krakow, Poland, pages 425–429. IEEE
Computer Society, 2006.
[30] H. Decker and D. Martinenghi. Can Integrity Tolerate Inconsistency? (Extended Ab-
stract). In Proceedings of the Fourteenth Italian Symposium on Advanced Database Systems,
SEBD 2006, Portonovo, Italy, June 18-21, 2006, pages 32–39, 2006. 18
[31] H. Decker and D. Martinenghi. Checking violation tolerance of approaches to database
integrity. In Advances in Information Systems, 4th International Conference, ADVIS 2006,
Izmir, Turkey, October 18-20, 2006, Pro- ceedings, volume 4243 of Lecture Notes in Com-
puter Science, pages 139– 148. Springer, 2006.
[32] H. Decker and D. Martinenghi. Integrity checking for uncertain data. In Proceedings of
the Second Twente Data Management Workshop on Un- certainty in Databases 6 June 2006,
Enschede, The Netherlands, CTIT Workshop Proceedings Series WP06-01, pages 41–48.
University of Twente, 2006.
[34] H. Decker and D. Martinenghi. Getting rid of straitjackets for flexible integrity check-
ing. In Proceedings of the 2nd International Workshop on Flex- ible Database and Infor-
mation System Technology (FlexDBIST-07), pages 360–364, 2007.
[35] H. Decker and D. Martinenghi. Classifying integrity checking methods with regard to
inconsistency tolerance. In Proceedings of the 10th International ACM SIGPLAN Confer-
ence on Principles and Practice of Declarative Programming, July 15-17, 2008, Valencia,
Spain, pages 195–204, 2008.
[38] H. Decker and D. Martinenghi. Modeling, measuring and monitoring the quality of in-
formation. In Proceedings of the 4th International Workshop on Quality of Information Sys-
tems (QoIS 2009), pages 212–221, 2009.
[42] I. F. Ilyas, D. Martinenghi, and M. Tagliasacchi. Rank-join algorithms for search com-
puting. In S. Ceri and M. Brambilla, editors, Search Computing: Challenges and Directions,
pages 211–224. 2009.
[43] A. Calì and D. Martinenghi. Conjunctive Query Containment under Access Limita-
tions. In Proceedings of Conceptual Modeling - ER 2008, 27th International Conference on
Conceptual Modeling, Barcelona, Spain, October 20-24, 2008, pages 326–340, 2008.
[44] A. Calì and D. Martinenghi. Querying Data under Access Limitations. In Proceedings
of the 24th International Conference on Data Engineering, ICDE 2008, April 7-12, 2008,
Cancu ́n, M ́exico, pages 50–59, 2008.
[45] A. Calì and D. Martinenghi. Optimizing Query Processing for the Hidden Web (Tuto-
rial). In Advances in Web Technologies and Applications, Pro- ceedings of the 12th Asia-
Pacific Web Conference, APWeb 2010, Busan, Korea, 6-8 April 2010, page 397, 2010.
[46] A. Calì and D. Martinenghi. Querying incomplete data over extended er schemata.
Theory and Practice of Logic Programming, 10(3):291–329, 2010.
[47] A. Calì and D. Martinenghi. Querying the deep web (tutorial). In EDBT 2010, 13th In-
ternational Conference on Extending Database Technology, Lausanne, Switzerland, March
22-26, 2010, Proceedings, pages 724–727, 2010.
[48] D. Martinenghi. A simplification procedure for integrity constraints. World Wide Web,
http://www.dat.ruc.dk/~dm/spic/index.html, 2003.
[49] D. Martinenghi. Optimal database locks for efficient integrity checking. In Eighth
East-European Conference on Advances in Databases and Information Systems (ADBIS
2004), Budapest, Hungary, 22-25 September 2004, local proceedings, pages 64–77, 2004.
[51] D. Martinenghi. Advanced Techniques for Efficient Data Integrity Checking. PhD the-
sis, Roskilde University, Dept. of Computer Science, Roskilde, Denmark, 2005. Available
in Datalogiske Skrifter, vol. 105, Roskilde Uni- versity, Denmark.
[52] D. Martinenghi. Access pattern. In H. C. van Tilborg and S. Jajodiathe, editors, Ency-
clopedia of Cryptography and Security (Second Edition), pages A17–A20. Springer,
2011. 20
[53] D. Martinenghi. On the difference between checking integrity constraints before or af-
ter updates. CoRR, submit/0864957, 2013.
[54] D. Martinenghi and H. Christiansen. Efficient integrity checking for databases with re-
cursive views. In Advances in Databases and Information Systems, 9th East European Con-
ference, ADBIS 2005, Tallinn, Estonia, September 12-15, 2005, Proceedings, volume 3631
of Lecture Notes in Computer Science, pages 109–124. Springer, 2005.
Notes in Computer Science, pages 606–615. Springer, 2005.
[57] D. Martinenghi and M. Tagliasacchi. Proximity Rank Join. Proceedings of the VLDB
Endowment, 3(1):352–363, 2010.
[58] D. Martinenghi and M. Tagliasacchi. Top-k pipe join. In Proceedings of the 4th Inter-
national Workshop on Ranking in Databases (DBRank 2010), pages 16–19. IEEE Computer
Society Press, 2010.
[59] D. Martinenghi and M. Tagliasacchi. Cost-Aware Rank Join with Random and Sorted
Access. IEEE Transactions on Knowledge & Data Engineering, 24(12):2143–2155, 2012.
[60] D. Martinenghi and M. Tagliasacchi. Proximity measures for rank join. ACM Transac-
tions on Database Systems, 37(1), 2012. Extended version of [57].
[61] A. Calì, D. Calvanese, and D. Martinenghi. Dynamic Query Optimization under Ac-
cess Limitations and Dependencies. Journal of Universal Com- puter Science, 15(21):33–62,
2009. 16
[63] A. Calì, L. V. S. Lakshmanan, and D. Martinenghi. Selected papers from the logic in
databases workshop 2008. Journal of Applied Logic, 8(2):151– 152, 2010.
[65] A. Calì, D. Calvanese, and D. Martinenghi. Optimization of query plans in the pres-
ence of access limitations. In Proc. of the ICDT 2007 Workshop on Emerging Research Op-
portunities in Web Data Management (EROW 2007), CEUR Electronic Workshop Proceed-
ings, http: //ceur-ws.org/, pages 33–47, 2007.