Modellazione dei dati in Cassandra

1. Panoramica

Cassandra è un database NoSQL che fornisce alta disponibilità e scalabilità orizzontale senza compromettere le prestazioni.

Per ottenere le migliori prestazioni da Cassandra, è necessario progettare attentamente lo schema attorno a modelli di query specifici per il problema aziendale in questione.

In questo articolo, esamineremo alcuni dei concetti chiave su come affrontare la modellazione dei dati in Cassandra .

Prima di procedere, puoi leggere il nostro articolo Cassandra con Java per comprendere le basi e come connetterti a Cassandra utilizzando Java.

2. Partition Key

Cassandra è un database distribuito in cui i dati vengono partizionati e archiviati su più nodi all'interno di un cluster.

La chiave di partizione è costituita da uno o più campi di dati e viene utilizzata dal partizionatore per generare un token tramite hashing per distribuire i dati in modo uniforme su un cluster .

3. Chiave di clustering

Una chiave di clustering è composta da uno o più campi e aiuta a raggruppare o raggruppare le righe con la stessa chiave di partizione e memorizzarle in ordine ordinato.

Diciamo che stiamo archiviando dati di serie temporali in Cassandra e vogliamo recuperare i dati in ordine cronologico. Una chiave di clustering che includa campi di dati di serie temporali sarà molto utile per un recupero efficiente dei dati per questo caso d'uso.

Nota: la combinazione di chiave di partizione e chiave di clustering costituisce la chiave primaria e identifica in modo univoco qualsiasi record nel cluster Cassandra.

4. Linee guida sui modelli di query

Prima di iniziare con la modellazione dei dati in Cassandra, dovremmo identificare i modelli di query e assicurarci che aderiscano alle seguenti linee guida:

  1. Ogni query dovrebbe recuperare i dati da una singola partizione
  2. Dobbiamo tenere traccia di quanti dati vengono archiviati in una partizione, poiché Cassandra ha limiti sul numero di colonne che possono essere archiviate in una singola partizione
  3. È consentito denormalizzare e duplicare i dati per supportare diversi tipi di modelli di query sugli stessi dati

Sulla base delle linee guida precedenti, esaminiamo alcuni casi d'uso del mondo reale e come modelleremmo i modelli di dati Cassandra per loro.

5. Esempi di modellazione dei dati del mondo reale

5.1. Post di Facebook

Supponiamo di memorizzare i post di Facebook di diversi utenti in Cassandra. Uno dei modelli di query più comuni sarà il recupero dei primi " N " post creati da un determinato utente.

Pertanto, abbiamo bisogno di memorizzare tutti i dati per un particolare utente su una singola partizione secondo le linee guida precedenti.

Inoltre, l'utilizzo del timestamp post come chiave di clustering sarà utile per recuperare i primi " N " post in modo più efficiente.

Definiamo lo schema della tabella Cassandra per questo caso d'uso:

CREATE TABLE posts_facebook ( user_id uuid, post_id timeuuid, content text, PRIMARY KEY (user_id, post_id) ) WITH CLUSTERING ORDER BY (post_id DESC);

Ora scriviamo una query per trovare i primi 20 post per l'utente Anna :

SELECT content FROM posts_facebook WHERE user_id = "Anna_id" LIMIT 20

5.2. Palestre in tutto il paese

Supponiamo di memorizzare i dettagli di diverse palestre partner nelle diverse città e stati di molti paesi e desideriamo recuperare le palestre per una determinata città.

Inoltre, supponiamo di dover restituire i risultati avendo le palestre ordinate in base alla data di apertura.

In base alle linee guida di cui sopra, dovremmo memorizzare le palestre situate in una data città di uno stato e un paese specifici su una singola partizione e utilizzare la data di apertura e il nome della palestra come chiave di raggruppamento.

Definiamo lo schema della tabella Cassandra per questo esempio:

CREATE TABLE gyms_by_city ( country_code text, state text, city text, gym_name text, opening_date timestamp, PRIMARY KEY ( (country_code, state_province, city), (opening_date, gym_name)) WITH CLUSTERING ORDER BY (opening_date ASC, gym_name ASC);

Ora, diamo un'occhiata a una query che recupera le prime dieci palestre entro la data di apertura per la città di Phoenix nello stato americano dell'Arizona:

SELECT * FROM gyms_by_city WHERE country_code = "us" AND state = "Arizona" AND city = "Phoenix" LIMIT 10

Successivamente, vediamo una query che recupera le dieci palestre aperte più di recente nella città di Phoenix, nello stato americano dell'Arizona:

SELECT * FROM gyms_by_city WHERE country_code = "us" and state = "Arizona" and city = "Phoenix" ORDER BY opening_date DESC LIMIT 10

Nota: poiché l'ordinamento dell'ultima query è opposto all'ordinamento definito durante la creazione della tabella, la query verrà eseguita più lentamente poiché Cassandra prima recupererà i dati e quindi li ordinerà in memoria.

5.3. Clienti e prodotti e-commerce

Supponiamo di gestire un negozio di e-commerce e di memorizzare le informazioni sul cliente e sul prodotto all'interno di Cassandra. Diamo un'occhiata ad alcuni dei modelli di query comuni in questo caso d'uso:

  1. Ottieni informazioni sui clienti
  2. Ottieni informazioni sul prodotto
  3. Ottieni tutti i clienti a cui piace un determinato prodotto
  4. Ottieni tutti i prodotti che piacciono a un determinato cliente

Inizieremo utilizzando tabelle separate per memorizzare le informazioni sul cliente e sul prodotto . Tuttavia, dobbiamo introdurre una discreta quantità di denormalizzazione per supportare la terza e la quarta query mostrate sopra.

We will create two more tables to achieve this – “Customer_by_Product” and “Product_by_Customer“.

Let's look at the Cassandra table schema for this example:

CREATE TABLE Customer ( cust_id text, first_name text, last_name text, registered_on timestamp, PRIMARY KEY (cust_id)); CREATE TABLE Product ( prdt_id text, title text, PRIMARY KEY (prdt_id)); CREATE TABLE Customer_By_Liked_Product ( liked_prdt_id text, liked_on timestamp, title text, cust_id text, first_name text, last_name text, PRIMARY KEY (prdt_id, liked_on)); CREATE TABLE Product_Liked_By_Customer ( cust_id text, first_name text, last_name text, liked_prdt_id text, liked_on timestamp, title text, PRIMARY KEY (cust_id, liked_on));

Note: To support both the queries, recently-liked products by a given customer and customers who recently liked a given product, we have used the “liked_on” column as a clustering key.

Let's look at the query to find the ten Customers who most recently liked the product “Pepsi“:

SELECT * FROM Customer_By_Liked_Product WHERE title = "Pepsi" LIMIT 10

And let's see the query that finds the recently-liked products (up to ten) by a customer named “Anna“:

SELECT * FROM Product_Liked_By_Customer WHERE first_name = "Anna" LIMIT 10

6. Inefficient Query Patterns

Due to the way that Cassandra stores data, some query patterns are not at all efficient, including the following:

  • Recupero dei dati da più partizioni : questo richiederà a un coordinatore di recuperare i dati da più nodi, archiviarli temporaneamente nell'heap e quindi aggregare i dati prima di restituire i risultati all'utente
  • Query basate su join : a causa della sua natura distribuita, Cassandra non supporta i join di tabella nelle query allo stesso modo di un database relazionale e, di conseguenza, le query con join saranno più lente e possono anche portare a problemi di incoerenza e disponibilità

7. Conclusione

In questo tutorial, abbiamo coperto diverse best practice su come affrontare la modellazione dei dati in Cassandra.

Comprendere i concetti fondamentali e identificare in anticipo i modelli di query è necessario per progettare un modello di dati corretto che ottenga le migliori prestazioni da un cluster Cassandra.