Datenmodellierung in Cassandra

1. Übersicht

Cassandra ist eine NoSQL-Datenbank, die hohe Verfügbarkeit und horizontale Skalierbarkeit bietet, ohne die Leistung zu beeinträchtigen.

Um die beste Leistung von Cassandra zu erzielen, müssen wir das Schema sorgfältig anhand von Abfragemustern entwerfen, die für das jeweilige Geschäftsproblem spezifisch sind.

In diesem Artikel werden einige der Schlüsselkonzepte zur Vorgehensweise bei der Datenmodellierung in Cassandra besprochen .

Bevor Sie fortfahren, können Sie unseren Artikel über Cassandra mit Java lesen, um die Grundlagen und die Verbindung zu Cassandra mit Java zu verstehen.

2. Partitionsschlüssel

Cassandra ist eine verteilte Datenbank, in der Daten auf mehrere Knoten innerhalb eines Clusters verteilt und gespeichert werden.

Der Partitionsschlüssel besteht aus einem oder mehreren Datenfeldern und wird vom Partitionierer verwendet, um ein Token über Hashing zu generieren, um die Daten gleichmäßig über einen Cluster zu verteilen .

3. Clustering-Schlüssel

Ein Clustering-Schlüssel besteht aus einem oder mehreren Feldern und hilft beim Clustering oder Gruppieren von Zeilen mit demselben Partitionsschlüssel und beim Speichern in sortierter Reihenfolge.

Angenommen, wir speichern Zeitreihendaten in Cassandra und möchten die Daten in chronologischer Reihenfolge abrufen. Ein Clustering-Schlüssel, der Zeitreihendatenfelder enthält, ist sehr hilfreich, um Daten für diesen Anwendungsfall effizient abzurufen.

Hinweis: Die Kombination aus Partitionsschlüssel und Clusterschlüssel bildet den Primärschlüssel und identifiziert jeden Datensatz im Cassandra-Cluster eindeutig.

4. Richtlinien zu Abfragemustern

Bevor wir mit der Datenmodellierung in Cassandra beginnen, sollten wir die Abfragemuster identifizieren und sicherstellen, dass sie den folgenden Richtlinien entsprechen:

  1. Jede Abfrage sollte Daten von einer einzelnen Partition abrufen
  2. Wir sollten nachverfolgen, wie viele Daten in einer Partition gespeichert werden, da Cassandra die Anzahl der Spalten, die in einer einzelnen Partition gespeichert werden können, begrenzt
  3. Es ist in Ordnung, die Daten zu denormalisieren und zu duplizieren, um verschiedene Arten von Abfragemustern für dieselben Daten zu unterstützen

Schauen wir uns anhand der oben genannten Richtlinien einige reale Anwendungsfälle an und wie wir die Cassandra-Datenmodelle für sie modellieren würden.

5. Beispiele für die Modellierung realer Daten

5.1. Facebook Beiträge

Angenommen, wir speichern Facebook-Beiträge verschiedener Benutzer in Cassandra. Eines der gängigen Abfragemuster ist das Abrufen der Top- N -Beiträge eines bestimmten Benutzers.

Daher müssen wir alle Daten für einen bestimmten Benutzer gemäß den oben genannten Richtlinien auf einer einzelnen Partition speichern .

Die Verwendung des Post-Zeitstempels als Clustering-Schlüssel ist außerdem hilfreich, um die Top- N -Posts effizienter abzurufen .

Definieren wir das Cassandra-Tabellenschema für diesen Anwendungsfall:

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);

Schreiben wir nun eine Abfrage, um die 20 besten Beiträge für die Benutzerin Anna zu finden :

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

5.2. Turnhallen im ganzen Land

Angenommen, wir speichern die Details verschiedener Partner-Fitnessstudios in den verschiedenen Städten und Bundesstaaten vieler Länder und möchten die Fitnessstudios für eine bestimmte Stadt abrufen.

Nehmen wir außerdem an, wir müssen die Ergebnisse zurückgeben, wenn die Turnhallen nach ihrem Eröffnungsdatum sortiert sind.

Basierend auf den oben genannten Richtlinien sollten wir die Fitnessstudios in einer bestimmten Stadt eines bestimmten Bundesstaates und Landes auf einer einzigen Partition speichern und das Eröffnungsdatum und den Namen des Fitnessstudios als Clustering-Schlüssel verwenden.

Definieren wir das Cassandra-Tabellenschema für dieses Beispiel:

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);

Schauen wir uns nun eine Abfrage an, die die ersten zehn Fitnessstudios nach ihrem Eröffnungsdatum für die Stadt Phoenix im US-Bundesstaat Arizona abruft:

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

Als nächstes sehen wir uns eine Abfrage an, die die zehn zuletzt eröffneten Fitnessstudios in der Stadt Phoenix im US-Bundesstaat Arizona abruft:

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

Hinweis: Da die Sortierreihenfolge der letzten Abfrage der bei der Tabellenerstellung definierten Sortierreihenfolge entgegengesetzt ist, wird die Abfrage langsamer ausgeführt, da Cassandra die Daten zuerst abruft und dann im Speicher sortiert.

5.3. E-Commerce-Kunden und -Produkte

Angenommen, wir betreiben einen E-Commerce-Shop und speichern die Kunden- und Produktinformationen in Cassandra. Schauen wir uns einige der gängigen Abfragemuster für diesen Anwendungsfall an:

  1. Erhalten Sie Kundeninfo
  2. Erhalten Sie Produktinfos
  3. Holen Sie sich alle Kunden, die ein bestimmtes Produkt mögen
  4. Holen Sie sich alle Produkte, die einem bestimmten Kunden gefallen

Wir beginnen mit der Verwendung separater Tabellen zum Speichern der Kunden- und Produktinformationen . Wir müssen jedoch ein angemessenes Maß an Denormalisierung einführen, um die oben gezeigten dritten und vierten Abfragen zu unterstützen.

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:

  • Abrufen von Daten von mehreren Partitionen - Dazu muss ein Koordinator die Daten von mehreren Knoten abrufen, vorübergehend im Heap speichern und die Daten dann aggregieren, bevor die Ergebnisse an den Benutzer zurückgegeben werden
  • Join-basierte Abfragen - Aufgrund seiner verteilten Natur unterstützt Cassandra Tabellenverknüpfungen in Abfragen nicht wie eine relationale Datenbank. Daher sind Abfragen mit Verknüpfungen langsamer und können auch zu Inkonsistenz- und Verfügbarkeitsproblemen führen

7. Fazit

In diesem Tutorial haben wir einige bewährte Methoden zur Vorgehensweise bei der Datenmodellierung in Cassandra behandelt.

Um ein korrektes Datenmodell zu entwerfen, das die beste Leistung eines Cassandra-Clusters erzielt, müssen Sie die Kernkonzepte verstehen und die Abfragemuster im Voraus identifizieren.