Vai al contenuto

Apache Cassandra: la guida completa

  • di

Overview

Cassandra è un datastore NoSQL open source e distribuito. Originariamente è stato sviluppato per Facebook da Avinash Lakshman e Prashant Malik, successivamente il progetto Cassandra è stato reso open source da Facebook nel 2008 ed è migrato ad Apache nel 2009.

Cassandra rientra nella categoria dei database NoSQL a colonne, offre un’elevata disponibilità senza avere un single point of failure. Dispone di un proprio linguaggio di interrogazione denominato Cassandra Query Language (CQL) molto simile all’SQL ma adattato alle caratteristiche di Cassandra.

Funzioni principali

Cassandra è uno dei pochi framework ad essere completamente distribuito, infatti non utilizza alcun master nella propria architettura. Tutti i cluster hanno i medesimi ruoli e possono elaborare tutte le interrogazioni del database, cosa che fa aumentare significativamente l’efficienza del sistema. I dati in Cassandra vengono distribuiti tra i nodi e la possibilità di aggiungerne degli altri rende il sistema altamente scalabile infatti, cosa molto importante: Cassandra riesce a scalare linearmente all’aumentare dei nodi che si aggiungono al cluster.

Per garantire disponibilità in caso di malfunzionamenti o guasti il framework Apache Cassandra è dotato di un sistema di replica configurabile in base ai propri scopi. La tolleranza agli errori può essere ridotta attraverso la replicazione automatica dei dati tra i nodi. I nodi non più funzionanti possono essere facilmente sostituiti e il sistema resta disponibile per le richieste in qualsiasi momento.

Secondo il teorema CAP, Cassandra offre inoltre un’elevata disponibilità e tolleranza alle partizioni di reti rinunciando alla consistenza e rendendolo quindi un framework di tipo AP.

Cassandra NON supporta joins, esatto avete capito bene, in Cassandra non si possono fare le join quindi bisogna trovare un meccanismo alternativo che vedremo in seguito.

Cassandra è un ottimo esempio di archivio distribuito. Funziona dividendo i dati in modo uniforme tra i nodi del cluster, che possono essere visualizzati come una topologia ad anello. Le righe del database sono mappate su un token, che a sua volta viene usato per dividere i dati tra i nodi. Ad esempio, per un dato con 128 token, il seguente anello Cassandra può essere progettato con 4 nodi, dove ogni nodo possiede un numero uguale di token. Tutti i dati mappati su un valore di token x si trovano in un singolo nodo. Di seguito un esempio:

I concetti principali

Tutti i dati salvati in cassandra sono associati ad un Token, il range dei token va da -2^63 a +2^63

VNode (Virtual Node): Ogni nodo definisce un numero di Virtual Nodes, questi Virtual Nodes funzionano come layer di indirezione,

Nota: si raccomanda l’utilizzo di 8 Virtual Nodes. Usando 8 Virtual Nodes il carico di lavoro si distribuisce nel sistema con una varianza pari a ~10% avendo così un impatto minimo sulle performance.

In Cassandra un cluster multi region equivale a diversi data centers in AWS, e i racks alle diverse Availability Zones AZ.

Le chiavi di Cassandra

Cassandra utilizza due tipi di chiavi:

  • La Partition Key è responsabile della distribuzione dei dati tra i nodi
  • La chiave di cluster è responsabile per l’ordinamento dei dati all’interno di una partizione

Una chiave primaria è una combinazione di questi tipi. Il vocabolario dipende dalla combinazione:

  • Semplice chiave primaria: solo la chiave di partizione, composta da una colonna
  • Chiave di partizione compost: solo la chiave di partizione, composta da più colonne
  • Chiave primaria composta: una chiave di partizione con una o più chiavi di clustering.
  • Chiave primaria composta e composta: una chiave di partizione composta da più colonne e più chiavi di clustering.

Keyspace

I dati in Cassandra sono organizzati in Keyspaces, all’interno di ogni Keyspace ci possono essere una o più tabelle, le tabelle sono divise in partizioni; In ogni partizione ci possono essere una o più Rows.

La strategia di replicazione dei dati è settata a livello di Keyspace;

Un’altra interessante strategia di replicazione è la NetworkTopology:

Replication factor

Cassandra memorizza le repliche dei dati su più nodi per garantire affidabilità e tolleranza ai guasti. La strategia di replicazione per ogni keyspace Edge determina i nodi in cui sono collocate le repliche.

Il numero totale di repliche per un keyspace in un cluster Cassandra è indicato come fattore di replicazione del keyspace. Un fattore di replica pari a 1 significa che c’è solo una copia di ogni dato nel cluster Cassandra. Un fattore di replica di due significa che ci sono due copie di ogni dato, dove ogni copia è su un nodo diverso. Tutte le repliche sono ugualmente importanti; non c’è una replica primaria o master.

In un sistema di produzione con tre o più nodi Cassandra in ogni centro dati, il fattore di replica predefinito per un keyspace Edge è tre. Come regola generale, il fattore di replica non dovrebbe superare il numero di nodi Cassandra nel cluster.

Se si aggiungono altri nodi Cassandra al cluster, il fattore di replicazione predefinito non viene modificato.

Per esempio, se si aumenta il numero di nodi Cassandra a sei, ma si lascia il fattore di replica a tre, non viene assicurato che tutti i nodi abbiano una copia di tutti i dati. Se un nodo va giù, un fattore di replica più alto significa una maggiore probabilità che i dati sul nodo esistano su uno dei nodi rimanenti. L’aspetto negativo di un fattore di replicazione più alto è una maggiore latenza nella scrittura dei dati.

Consistency level

Il livello di consistenza di Cassandra è definito come il numero minimo di nodi Cassandra che devono riconoscere un’operazione di lettura o scrittura prima che l’operazione possa essere considerata riuscita. Diversi livelli di consistenza possono essere assegnati a diversi keyspace.

Il livello di coerenza predefinito è ONE per tutte le operazioni di scrittura e lettura.

Write consistency levels

Questa tabella descrive i livelli di consistenza di scrittura nell’ordine dal più forte al più debole.

LivelloDescrizioneUtilizzo
ALLUna scrittura deve essere scritta nel log di commit e nella Memtable di tutti i nodi di replica nel cluster per quella partizione.Fornisce la più alta consistenza e la più bassa disponibilità tra tutti gli altri livelli.
EACH_QUORUMStrong consistency. Una scrittura deve essere scritta nel commitlog e nella memtable su un quorum di nodi di replica in ogni datacenter.Usato in cluster composti da più datacenter per mantenere strettamente la consistenza allo stesso livello in ogni datacenter. Per esempio, va scelto questo livello se si vuole che una scrittura fallisca quando un datacenter è fuori uso e il QUORUM non può essere raggiunto su quel datacenter.
QUORUMUna richiesta di scrittura deve essere scritta nel commitlog e nella memtable su un quorum di nodi di replica in tutti i datacenter.Usato in cluster di uno o più datacenter per mantenere una consistenza forte nel cluster. Va usata se si può tollerare un certo livello di fallimento.
LOCAL_QUORUMConsistenza forte. Una richiesta di scrittura deve essere scritta nel commitlog e nella memtable su un quorum di nodi di replica nello stesso datacenter del coordinatore. Evita la latenza della comunicazione infra-datacenter.Usato in cluster di più datacenter con una strategia di posizionamento della replica consapevole del rack, come NetworkTopologyStrategy, e uno snitch correttamente configurato. Si usa per mantenere la consistenza a livello locale (all’interno del singolo datacenter). Può essere usata con SimpleStrategy.
ONEUna richiesta di scrittura deve essere scritta nel commitlog e nella memtable di almeno un nodo di replica.E’ molto usata poiché i requisiti di coerenza non sono rigorosi. E’ molto veloce.
TWOUna richiesta di scrittura deve essere scritta nel commitlog e nella memtable di almeno due nodi di replica.Simile alla ONE
THREEUna richiesta di scrittura deve essere scritta nel commitlog e nella memtable di almeno tre nodi di replica.Simile alla TWO
LOCAL_ONEUna richiesta di scrittura deve essere inviata e confermata correttamente da almeno un nodo di replica nel data center locale.In un cluster di più datacenter, un livello di coerenza di UNO è spesso desiderabile, ma il traffico cross-Datacenter non lo è. LOCAL_ONE realizza questo. Per ragioni di sicurezza e qualità, puoi usare questo livello di coerenza in un datacenter offline per prevenire la connessione automatica ai nodi online in altri datacenter se un nodo offline va giù.
ANYUna richiesta scrittura deve essere scritta su almeno un nodo. Se tutti i nodi di replica per la chiave di partizione data sono giù, la scrittura può ancora avere successo dopo che è stato scritto un hinted handoff. Se tutti i nodi di replica sono giù al momento della scrittura, una scrittura ANY non è leggibile fino a quando i nodi di replica per quella partizione non sono tornati online.Fornisce una bassa latenza e la garanzia che una scrittura non fallisca mai. Offre la più bassa consistenza e la più alta disponibilità.

Read consistency levels

Questa tabella descrive i livelli di consistenza di lettura nell’ordine dal più forte al più debole.

LivelloDescrizioneUtilizzo
ALLRestituisce il record dopo che tutte le repliche hanno risposto. L’operazione di lettura fallisce se una replica non risponde.Fornisce la più alta consistenza tra tutti i livelli e la più bassa disponibilità di tutti i livelli.
EACH_QUORUMNon supportata per la lettura.
QUORUMRestituisce il record dopo che un numero di repliche pari al quorum (maggioranza) ha risposto da tutti i datacenter.Usato in cluster di uno o più datacenter per mantenere una consistenza forte nel cluster. Assicura una forte consistenza a patto che si possa tollerare un certo livello di fallimento.
LOCAL_QUORUMRestituisce il record dopo che un quorum di repliche nel datacenter ha risposto coordinatore. Evita la latenza della comunicazione tra datacenter.Usato in cluster multipli di data center con una strategia di posizionamento della replica consapevole dei rack (NetworkTopologyStrategy) e uno snitch correttamente configurato. Fallisce quando si usa SimpleStrategy.
ONERestituisce una risposta dalla replica più vicina, come determinato dallo snitch.Fornisce la massima disponibilità tra tutti i livelli se si può tollerare una probabilità relativamente alta di lettura di dati non aggiornati. Le repliche contattate per la lettura potrebbero non avere sempre la scrittura più recente.
TWORestituisce i dati più recenti da due delle repliche più vicine.Simile alla ONE
THREERestituisce i dati più recenti da tre delle repliche più vicine.Simile alla TWO
LOCAL_ONERestituisce una risposta dalla replica più vicina nel datacenter locale.In un cluster di più datacenter, un livello di coerenza di UNO è spesso desiderabile, ma il traffico cross-Datacenter non lo è. LOCAL_ONE realizza questo. Per ragioni di sicurezza e qualità, puoi usare questo livello di coerenza in un datacenter offline per prevenire la connessione automatica ai nodi online in altri datacenter se un nodo offline va giù.
SERIALPermette di leggere lo stato corrente (e possibilmente non committato) dei dati senza proporre una nuova aggiunta o un aggiornamento. Se una lettura SERIAL trova una transazione uncommitted in corso, impegna la transazione come parte della lettura. Simile a QUORUM.Per leggere l’ultimo valore di una colonna dopo che un utente ha invocato una transazione leggera per scrivere sulla colonna, usare SERIAL. Cassandra controlla quindi la transazione leggera in corso per gli aggiornamenti e, se li trova, restituisce i dati più recenti.
LOCAL_SERIALCome SERIAL, ma limitato al datacenter. Simile a LOCAL_QUORUM.Usato per ottenere una coerenza linearizzabile per transazioni leggere.

Quando ci si connette a Cassandra per operazioni di lettura e scrittura, i nodi del Message Processor e del Management Server usano tipicamente il valore Cassandra di LOCAL_QUORUM per specificare il livello di consistenza per un keyspace. Tuttavia, alcuni keyspace sono definiti per utilizzare un livello di consistenza di uno.

Il calcolo del valore di QUORUM per un datacenter è:

LOCAL_QUORUM = (replication_factor / 2) + 1

Il quorum viene calcolato, e poi arrotondato per difetto ad un numero intero, quindi se replication_factor = 3, QUORUM = (3 / 2) + 1 = 2.5 = 2

Per un cluster con più datacenter il quorum è calcolato utilizzando la somma del fattore di replicazione per ogni datacenter:

QUORUM = (sum_of_replication_factors / 2) + 1

sum_of_replication_factors = datacenter1_RF + datacenter2_RF + . . . + datacentern_RF

Esempi:

  • Usando un fattore di replica di 3, il quorum è di 2 nodi. Il cluster tollera al più 1 replica fuori uso.
  • Usando un fattore di replica di 6, il quorum è 4. Il cluster tollera al più 2 repliche fuori uso.
  • In un cluster di due datacenter dove ogni datacenter ha un fattore di replica di 3, il quorum è di 4 nodi. Il cluster può tollerare 2 nodi di replica fuori uso.
  • In un cluster di cinque datacenter dove due datacenter hanno un fattore di replica di 3 e tre datacenter hanno un fattore di replica di 2, il quorum è di 7 nodi.

Più datacenter ci sono, più alto è il numero di nodi di replica che devono rispondere per conseguire il successo di un’operazione.

Simile a QUORUM, il livello LOCAL_QUORUM è calcolato in base al fattore di replica dello stesso datacenter del nodo coordinatore. Cioè, anche se il cluster ha più di un datacenter, il quorum è calcolato solo con i nodi replica locali.

In EACH_QUORUM, ogni datacenter nel cluster deve raggiungere un quorum basato sul fattore di replica di quel datacenter affinché la richiesta di scrittura abbia successo. Cioè, per ogni centro dati nel cluster un quorum di nodi di replica deve rispondere al nodo coordinatore affinché la richiesta di scrittura abbia successo.

Se impostiamo come Consistency level = ALL e un nodo va offline, un’eventuale richiesta di scrittura fallirà perché non riuscirà a raggiungere il livello di consistenza richiesto.

Se invece impostiamo il livello di consistenza su QUORUM e un nodo è offline il messaggio o i messaggi che andremo a scrivere verranno scritti nelle repliche che appartengono al quorum, in più verranno scritti dal coordinator anche nell’Hinted handoff in modo che quando il nodo tornerà online verrà informato delle informazioni arrivate mentre era offline.

Hinted handoof

Hinted Handoff è una parte opzionale delle scritture il cui scopo principale è quello di fornire un’estrema disponibilità di scrittura quando la consistenza non è richiesta.

Ogni volta che un nodo non risponde o è inattivo per un certo periodo di tempo, tutte le richieste di scrittura a quel nodo falliscono. Cassandra mantiene una copia delle partizioni che dovevano essere scritte sul nodo che non risponde all’interno di una tabella locale di hints. Gli hints sono memorizzati per un certo periodo di tempo configurabile. Quando il nodo inattivo si rialza e inizia a comunicare con gli altri nodi tramite gossiping, gli hints vengono ricevuto dal nodo che era andato offline, e i dati sono di nuovo sincronizzati tra tutti i nodi di replica.

Il nodo coordinatore alla fine elimina gli hints se il nodo inattivo non si rialza entro il periodo di eliminazione. Il coordinatore smette anche di memorizzare gli hints relativi ad un nodo inattivo se questo è inattivo per un periodo di tempo configurabile.

Quale è l’uso delle SSTable in Cassandra?

Lo scopo di un database è quello di memorizzare dati in modo persistente ed efficiente. Questa memorizzazione deve essere durevole, in modo che i dati non vengano persi quando il sistema viene spento o si verifica un errore. Mantenere tutti i dati solo in memoria sarebbe veloce, ma non duraturo. Scrivere immediatamente ogni aggiornamento nella memoria sarebbe molto lento e inefficiente su larga scala.

Qui è dove abbiamo bisogno di capire Memtable vs. SSTable. Quando i dati sono committati (inviati a cassandra), Cassandra memorizza le modifiche in un commitlog, che è un file che permette solo l’aggiunta, quindi le scritture sono veloci. Contemporaneamente i dati vengono scritti in una cache in-memoria di dati chiave/colonna chiamata memtable. Periodicamente viene fatto il flush della memtable su uno storage persistente sotto forma di SSTables su disco. Le SSTables in Cassandra servono come i blocchi di costruzione dei dati totali memorizzati nel database. Le SSTable sono immutabili, quindi gli aggiornamenti dei dati creano un nuovo file SSTable invece di cambiare quelli esistenti.

Per ogni SSTable il database crea un file di indice e un file di dati. Il file di indice aiuta a localizzare i dati più velocemente nel file di dati ordinati.

Una SSTable usa un formato di struttura dati ad albero Log-Structured Merge (LSM) . Questo formato è più efficiente per insiemi di dati estremamente grandi e in rapida crescita rispetto al tradizionale formato B-tree.

CQL (Cassandra Query Language)

I Keyspaces sono i componenti principali per organizzare i dati in Cassandra, CQL fornisce diversi comandi per manipolare i Keyspaces:

Create

CREATE KEYSPACE afjcjsbx WITH REPLICATION = { ‘class’ : ‘NetworkTopologyStrategy’, ‘DC1’: 3} AND DURABLE_WRITES = false;

Andando a settare DURABLE_WRITES = false andremo a dire a Cassandra di non scrivere i dati sul commit log quando andremo a scrivere i dati nelle tabelle di questo keyspace;

Alter

ALTER KEYSPACE afjcjsbx WITH REPLICATION = { ‘class’ : ‘SimpleStrategy’, ‘replication_factor’: 3} AND DURABLE_WRITES = true;

Un Keyspace può essere anche modificato andando a cambiare alcuni parametri quali la Strategy o le DURABLE_WRITES, dopo aver effettuato la modifica però dobbiamo effettuare una repair in modo da far riorganizzare a Cassandra i dati in accordo con la nuova strategy;

Drop

DROP KEYSPACE afjcjsbx;

Un Keyspace può essere anche eliminato andando a cancellare di conseguenza tutte le tabelle in esso contenute;

Create

CREATE TABLE afjcjsbx.books (id varchar PRIMARY KEY);

Alter

ALTER TABLE afjcjsbx.books ADD name varchar;
ALTER TABLE afjcjsbx.books DROP title varchar;

Truncate

TRUNCATE afjcjsbx.books;

Drop

DROP TABLE afjcjsbx.books;

All’interno di un Keyspace possiamo creare tabelle, modificarle, svuotarle ed eliminarle.

CREATE TABLE afjcjsbx.books (id varchar PRIMARY KEY) WITH comment=’A table of books’;

In Cassandra quando creiamo una Tabella si possono settare anche diverse proprietà come:

CQL propertyDescrizione
bloom_filter_fp_chanceProbabilità di falso positivi desiderata per i filtri Bloom delle SSTable.
cachingOttimizza l’uso della memoria cache senza l’ottimizzazione manuale.
commentUn commento leggibile che descrive la tabella.
compactionImposta la strategia di compattazione per la tabella.
compressionImposta l’algoritmo di compressione; Valori validi sono: LZ4Compressor, SnappyCompressor, DeflateCompressor.
dclocal_read_repair_chanceLa probabilità che un’operazione di lettura riuscita inneschi una riparazione di lettura. A differenza della riparazione controllata da read_repair_chance, questa riparazione è limitata alle repliche nello stesso DC del coordinatore. Il valore deve essere compreso tra 0 e 1.
default_time_to_liveIl valore di questa proprietà è un numero di secondi. Se è impostato, Cassandra applica un marcatore TTL predefinito ad ogni colonna della tabella, impostato a questo valore. Quando il TTL della tabella viene superato, Cassandra mette in “tombstone” la tabella.
gc_grace_secondsIl numero di secondi dopo che i dati sono marcati come “tombstone” (marcatore di cancellazione) prima che siano eleggibili per il garbage collector. Cassandra non eseguirà hints o mutazioni in batch su un record marcato “tombstone” entro il suo gc_grace_period. Il valore predefinito permette a Cassandra di massimizzare la consistenza prima della cancellazione.
min_index_interval, max_index_intervalPer controllare il campionamento delle voci dell’indice della partizione, configurate la sequenza di campionamento del sommario della partizione cambiando queste proprietà.
memtable_flush_period_in_msIl numero di millisecondi prima che Cassandra cancelli le memtables associate a questa tabella.
read_repair_chanceLa probabilità che un’operazione di lettura di successo inneschi una riparazione di lettura. A differenza della riparazione controllata da dc_local_read_repair_chance, questa riparazione non è limitata alle repliche nello stesso DC del coordinatore. Il valore deve essere compreso tra 0 e 1.
speculative_retrySovrascrive il normale timeout di lettura quando read_repair_chance non è 1.0, inviando un’altra richiesta di lettura.

Tipi di dato base in Cassandra

Numeric

bigint, decimal, double, float, int, varint

String

ascii, text, varchar

Date

timestamp, timeuuid

Other

boolean, uuid, inet, blob

Problemi con i nomi dei Keyspace, Tabelle, Colonne

In Cassandra ci sono delle regole da rispettare quando assegnamo i nomi a keyspace, tabelle, colonne; I loro nomi non devono contenere:

  • Trattini
  • Spazi

Chiave Primaria e Chiave Primaria Composta

CREATE TABLE afjcjsbx.books (id varchar PRIMARY KEY, title varchar, author varchar);

CREATE TABLE afjcjsbx.books (id varchar, title varchar, author varchar, PRIMARY KEY ((id, author)));

  • In Cassandra la chiave primaria è anche utilizzata come chiave di partizione,

Selectiong Data

SELECT id, title FROM afjcjsbx.books;

Interrogare le Tabelle in Cassandra è molto simile a come lo si fa nei Database relazionali, la Query di sopra ci restituirà tutti gli id e il titolo dei corsi, ma bisogna eseguire con attenzione questa Query perché non essendo specificata la clausola WHERE non è limitata ad una specifica partizione ma ci restituirà il risultato calcolato per ogni partizione. Quindi il coordinatore dovrà andare ad interrogare ogni nodo ed aspettare il risultato per ognuno di essi rendendola di fatto molto lenta.

SELECT title, duration AS length FROM afjcjsbx.books WHERE id = ‘treasure-island’;

Le Query in Cassandra supportano anche degli Alias proprio come nell’SQL tradizionale.

SELECT title, duration AS length FROM afjcjsbx.books WHERE id IN (‘treasure-island’, ‘shining’);

Si possono specificare anche una serie di valori o limitarli

SELECT * FROM afjcjsbx.books LIMIT 100;

Inserting and Updating Data

Per inserire i dati e modificarli possiamo invece:

Insert

INSERT INTO afjcjsbx.books (id, author) VALUES (‘treasure-island’, ‘robert-luis-stevenson’);

Update

UPDATE INTO afjcjsbx.books SET author = ‘robert-stevenson’ WHERE id = ‘treasure-island’;

UPDATE INTO afjcjsbx.books SET author = ‘robert-stevenson’ WHERE id IN (‘treasure-island’, ‘strange-case-of-dr-jekyll-and-mr-hyde’);

Se andiamo ad inserire dati già esistenti quelli verranno aggiornati (Upsert);

Deleting Data

Deleting a row

DELETE FROM afjcjsbx.books SET author = ‘robert-stevenson’ WHERE id = ‘treasure-island’;

Deleting a column

DELETE author FROM afjcjsbx.books WHERE id = ‘treasure-island’;

UPDATE afjcjsbx.books SET author = null WHERE id = ‘treasure-island’;

INSERT INTO afjcjsbx.books (id, author) VALUES (the-green-mile, null);

In cassandra possiamo sia cancellare dei dati che cancellare una colonna,
nella delete le 3 espressioni sono equivalenti, quindi ci sono diversi modi per eliminare una colonna, tutti e 3 equivalenti;

In Cassandra si possono eliminare le colonne anche senza scrivere nessuna query, ma utilizzando il TTL (Time-To-Live);

Expiring Data with TTLs

Set the TTL for a single column value

UPDATE afjcjsbx.users USING TTL 32400 SET reset_token = ‘1fgK84’ WHERE* id = ‘jack99’;

Retrieve the TTL for a column value

SELECT TTL(reset_token) FROM afjcjsbx.users WHERE id = ‘jack99’;

è espresso in secondi e può essere settato anche a livello di singola colonna o tabella;
Una row viene eliminata quando tutti i TTL di tutte le colonne scadono.

Un caso di uso comune in cui è ottimale usare il TTL è per esempio quando abbiamo la necessità di mantenere i token per i reset della pasword di un utente (es. ogni 90 giorni la password deve essere cambiata)

Set the TTL for an entire row

INSERT INTO afjcjsbx.reset_tokens (id, token) VALUES (‘jack99’, ‘ad4VF9’) USING TTL 10800;

Set a table wide, default TTL

CREATE TABLE reset_tokens (id varchar PRIMARY KEY, token varchar) WITH default_time_to_live = 10800;

Quando i dati vengono eliminati in Cassandra questi non vengono eliminati immediatamente dai dischi del cluster, ma un valore speciale chiamato Tombstone viene scritto nel database per indicare i dati in questione come eliminati, questi Tombstone impediscono la restituzione dei dati durante le letture e alla fine consentono di eliminare i dati tramite la compattazione, i dati di tipo Tombstone sono partizionati come qualsiasi altro dato nel database.

Le Tombstone sono scritture: seguono il normale percorso di una scrittura, occupano spazio su disco e utilizzano i meccanismi di coerenza di Cassandra. Le Tombstone possono essere propagate attraverso il cluster tramite Hints e riparazioni. Se un cluster è gestito correttamente garantisce che i dati rimarranno eliminati anche se un nodo è inattivo quando viene emessa l’eliminazione.

Le Tombstone vengono scritte con un timestamp. In circostanze ideali, le Tombstone (e i relativi dati associati) verranno cancellati durante la compattazione dopo che è trascorso un certo periodo di tempo.

Il numero di secondi prima che il garbage collection rimuova le Tombstone e i dati è chiamato gc_grace_seconds e di default è settato a 864000 l’equivalente di 10 giorni.

Esempio:

Abbiamo un fattore di replicazione pari a 3, effettuiamo una eliminazione ma la conferma la riceviamo solo da due nodi su 3 perché un nodo è andato offline, se nel frattempo viene fatta la purge delle Tombstone prima che il nodo crashato torni su, nel momento in cui il nodo torna online e si sincronizzerà troverà che lui è l’unico a mantenere una copia dei dati quindi un read repair copierà i dati sui due nodi che contenevano le informazioni precedentemente, in questo modo i dati che abbiamo provato ad eliminare saranno tornati in vita!

In progress..

Riferimenti

[1] Apache Cassandra: Open Source NoSQL Database
https://cassandra.apache.org/_/index.html