Home Up PDF Prof. Dr. Ingo Claßen
Cassandra - ADBKT

Cassandra Einordnung

  • Open-Source-Datenbank der Apache Software Foundation
  • Ursprünglich von Facebook entwickelt (2008), 2009 Open Source
  • Kombiniert Ideen aus Amazon Dynamo (Replikation, Peer-to-Peer) und Google Bigtable (Wide Column)
  • Kategorie: Wide Column Store (auch: Wide-Column-Family-Store)
  • Ausgelegt auf extreme Schreiblast, hohe Verfügbarkeit, lineare Skalierbarkeit
  • Kein Single Point of Failure – vollständig masterlos

Wide Column Store Konzept

Vergleich der Modelle

  • Relational: festes Schema, Zeilen mit gleichen Spalten, Joins
  • Key-Value: Schlüssel → opaker Wert, keine Struktur
  • Wide Column: Schlüssel → Menge von typisierten Spalten, pro Row variabel

Eigenschaften

  • Sparse Data: fehlende Spalten belegen keinen Speicher
  • Spalten innerhalb einer Row sortiert gespeichert
  • Sehr effizient für Zeitreihendaten und Aggregationen über Spalten

Datenmodell: Keyspace

  • Keyspace = Äquivalent zu einer Datenbank in relationalen Systemen
  • Enthält mehrere Tabellen
  • Replikationsfaktor (RF): Anzahl der Kopien jedes Datensatzes
  • Replikationsstrategie bestimmt, auf welche Nodes Daten verteilt werden

Strategien

  • SimpleStrategy: für Single-Datacenter, nächste Nodes im Ring
  • NetworkTopologyStrategy: für Multi-Datacenter, RF pro Datacenter konfigurierbar
CREATE KEYSPACE sensor_data
  WITH replication = {
    'class': 'NetworkTopologyStrategy',
    'dc1': 3,
    'dc2': 2
  };

Datenmodell: Tabelle und Partition

  • Tabelle: Schema mit festen Spaltendefinitionen
  • Partition: Gruppe von Rows mit gleichem Partition Key → physische Speichereinheit
  • Partition Key: bestimmt, auf welchem Node Daten liegen
  • Clustering Key: Sortierung der Rows innerhalb einer Partition
  • Columns: reguläre Datenspalten (typisiert)

Partition Key

  • Bestimmt die physische Verteilung im Cluster
  • Hash-Funktion (Murmur3) → Token → Node-Zuweisung im Ring
  • Alle Rows einer Partition liegen auf denselben Nodes
  • Abfragen ohne Partition Key erfordern Cluster-Scan (ineffizient)

Hot Partitions vermeiden

  • Schlecht: date als einziger Partition Key (alle Writes heute → ein Node)
  • Besser: (sensor_id, date) → gleichmäßige Verteilung
  • Ziel: Partitionen möglichst gleich groß, max. ~100 MB empfohlen

Clustering Key

  • Sekundärer Teil des Primary Key: PRIMARY KEY (partition_key, clustering_key)
  • Definiert die Sortierreihenfolge der Rows innerhalb einer Partition
  • Ermöglicht effiziente Bereichsabfragen (BETWEEN, <, >, ORDER BY)
  • Mehrere Clustering Keys möglich (Compound Primary Key)
  • Sortierrichtung pro Clustering Key konfigurierbar (ASC / DESC)
CREATE TABLE messwerte (
  sensor_id  TEXT,
  zeitpunkt  TIMESTAMP,
  temperatur DOUBLE,
  PRIMARY KEY (sensor_id, zeitpunkt)
) WITH CLUSTERING ORDER BY
    (zeitpunkt DESC);

Ergebnis

sensor_id  | zeitpunkt           | temperatur
-----------+---------------------+-----------
s-001      | 2024-06-01 12:00:00 | 23.4
s-001      | 2024-06-01 11:00:00 | 22.8
s-001      | 2024-06-01 10:00:00 | 22.1

CQL: Tabelle anlegen

Keyspace erstellen

CREATE KEYSPACE mein_ks
  WITH replication = {
    'class': 'SimpleStrategy',
    'replication_factor': 3
  };

Tabelle erstellen

CREATE TABLE mein_ks.benutzer (
  benutzer_id UUID,
  nachname    TEXT,
  vorname     TEXT,
  email       TEXT,
  erstellt    TIMESTAMP,
  PRIMARY KEY (benutzer_id)
);

Compound Primary Key

CREATE TABLE mein_ks.bestellungen (
  kunden_id   UUID,
  bestell_ts  TIMESTAMP,
  produkt_id  UUID,
  menge       INT,
  preis       DECIMAL,
  PRIMARY KEY (kunden_id, bestell_ts)
) WITH CLUSTERING ORDER BY
    (bestell_ts DESC);

Hinweise

  • CQL (Cassandra Query Language) ist SQL-ähnlich
  • Keine Fremdschlüssel, keine Joins

CQL: Schreiben und Lesen

Schreiben

INSERT INTO messwerte
  (sensor_id, zeitpunkt, temperatur)
VALUES
  ('s-001', toTimestamp(now()), 23.5);

UPDATE messwerte
SET temperatur = 24.0
WHERE sensor_id = 's-001'
  AND zeitpunkt = '2024-06-01 12:00:00';

DELETE FROM messwerte
WHERE sensor_id = 's-001'
  AND zeitpunkt = '2024-06-01 10:00:00';

Lesen

-- Effizient: Partition Key angegeben
SELECT * FROM messwerte
WHERE sensor_id = 's-001';

-- Bereichsabfrage auf Clustering Key
SELECT * FROM messwerte
WHERE sensor_id = 's-001'
  AND zeitpunkt > '2024-06-01 00:00:00';

-- Achtung: ALLOW FILTERING → Full Scan
SELECT * FROM messwerte
WHERE temperatur > 25.0
ALLOW FILTERING;
  • WHERE ohne Partition Key → ineffizient, Warnung
  • ALLOW FILTERING explizit erforderlich

Datenmodellierung: Query-First

  • Kein Join-Support: Daten müssen bereits in der richtigen Form gespeichert sein
  • Kein ad-hoc Querying: beliebige WHERE-Bedingungen nicht möglich ohne ALLOW FILTERING
  • Modell an Zugriffsmustern ausrichten: zuerst definieren, welche Abfragen gestellt werden, dann Tabellen entwerfen
  • Denormalisierung: Daten werden bewusst dupliziert, um Joins zu vermeiden
  • Eine Abfrage = eine Tabelle: für jedes Zugriffsmuster ggf. eigene Tabelle
  • Cassandra Data Modeling (link)

Vorgehen

1. Anforderungen erfassen
   → Welche Abfragen werden gestellt?
   → Welche Filter? Welche Sortierung?

2. Zugriffsmuster auflisten
   → GET sensor by ID
   → GET latest readings for sensor
   → GET all sensors in region

3. Tabellen entwerfen
   → Partition Key aus Filterbedingung
   → Clustering Key aus Sortierung
Anti-Pattern:
  SELECT * FROM sensoren
  WHERE region = 'Berlin'
  AND typ = 'Temperatur'
  ORDER BY wert DESC
  → Mehrere Nicht-PK-Filter: ALLOW FILTERING

Lösung: eigene Tabelle für diesen Query
  CREATE TABLE sensoren_by_region_typ (
    region TEXT,
    typ    TEXT,
    wert   DOUBLE,
    id     UUID,
    PRIMARY KEY ((region, typ), wert)
  ) WITH CLUSTERING ORDER BY (wert DESC);

Beispiel Zeitreihendaten

Anforderung

  • Sensormesswerte speichern: Temperatur, feuchtigkeitigkeit
  • Abfrage: alle Messwerte eines Sensors der letzten Stunde
  • Viele Sensoren, hohe Schreibrate (1 Wert/s pro Sensor)

Schema-Design

CREATE TABLE messwerte_stündlich (
  sensor_id   TEXT,
  stunde      TEXT,        -- 'YYYY-MM-DD-HH'
  zeitpunkt   TIMESTAMP,
  temperatur  DOUBLE,
  feuchtigkeit  DOUBLE,
  PRIMARY KEY ((sensor_id, stunde), zeitpunkt)
) WITH CLUSTERING ORDER BY
    (zeitpunkt DESC)
  AND default_time_to_live = 2592000;
  -- 30 Tage TTL

Abfragen

-- Letzte Stunde eines Sensors
SELECT * FROM messwerte_stündlich
WHERE sensor_id = 's-001'
  AND stunde = '2024-06-01-12';

-- Einfügen (Batch für Atomarität)
BEGIN BATCH
  INSERT INTO messwerte_stündlich
    (sensor_id, stunde, zeitpunkt,
     temperatur, feuchtigkeit)
  VALUES
    ('s-001', '2024-06-01-12', '2024-06-01 12:05:00', 23.5, 61.2);
APPLY BATCH;

Partitionsgröße kontrollieren

  • Compound Partition Key (sensor_id, stunde) begrenzt Partition auf 3.600 Rows/h
  • Verhindert unbegrenzt wachsende Partitionen

Cassandra vs. Relationale DB

Stärken Cassandra

  • Lineare horizontale Skalierbarkeit (Schreiben und Lesen)
  • Keine Single Point of Failure, masterlose Architektur
  • Extrem hohe Schreibdurchsatz (append-only, CommitLog)
  • Multi-Datacenter-Replikation nativ unterstützt
  • Tunable Consistency: Tradeoff zwischen Konsistenz und Verfügbarkeit
  • Ideal für Zeitreihendaten, IoT, hohe Schreiblast

Schwächen Cassandra

  • Kein Joins, kein flexibles Querying
  • Modellierung komplex (Query-First, Denormalisierung)
  • Keine starken Transaktionen über Partitionen (nur Lightweight Transactions)

Stärken Relationale DB

  • Volle ACID-Transaktionen über mehrere Tabellen
  • Flexible ad-hoc-Abfragen mit Joins und komplexem SQL
  • Normalisierung verhindert Datenduplikation
  • Starke Konsistenz standardmäßig
  • Reifes Ökosystem, breite Tool-Unterstützung

Anwendungsfälle

Typische Einsatzgebiete

  • IoT / Zeitreihendaten: Sensordaten, Messwerte, Metriken
  • Messaging: Inbox-Verwaltung, Chat-Verläufe (WhatsApp nutzte Cassandra)
  • Empfehlungssysteme: User-Activity-Logs, Click-Streams
  • Content-Delivery: User-Profile, Session-Daten
  • Finanzdaten: Transaktionshistorie, Audit-Logs

Cassandra in der Praxis

  • Netflix: Viewing-History, User-Profile (Milliarden von Rows)
  • Apple: iCloud-Dienste, über 75.000 Cassandra-Nodes
  • Instagram: Direct Messages, Aktivitäts-Feed
  • Uber: Fahrthistorie, Geo-Daten
  • Discord: Message-Speicherung (Milliarden von Nachrichten)

Managed Angebote

  • DataStax Astra DB (DBaaS auf Basis von Cassandra)
  • Amazon Keyspaces (Cassandra-kompatibel, serverless)
  • Azure Managed Instance for Apache Cassandra