Teil 1: Das Datenbanksystem
Apache Cassandra ist ein horizontal skalierendes, Master-loses Datenbanksystem, das durch einen Ring-Cluster realisiert wird. Doch was genau bedeutet dies?
Der Cluster
- Wie bereits in einem vorherigen Artikel einer allgemeinen Einführung zum Thema NoSQL beschrieben, bedeutet horizontale Skalierung, dass beim Auftreten eines Engpasses bezüglich CPU, Speicher oder Storage einfach ein weiterer Knoten in einen Cluster hinzugefügt werden kann. Dieser kann nach kürzester Zeit Last übernehmen und somit den Engpass beheben.
- In einem Master-losen Ring-Cluster sind alle Knoten des Systems gleichberechtigt: Jeder Knoten kann Anfragen eines Clients entgegen nehmen und entweder direkt selber verarbeiten oder an einen anderen Knoten delegieren. Solange von einem Client aus auch nur ein Knoten im Netz sichtbar ist, wird der Cluster funktionieren und antworten.
Ob diese Antwort konsistent ist, hängt von der internen Kommunikation der Knoten im Ring ab. Dies ist die Aussage des bekannten CAP-Theorems.
Replikation
Im Ring-Cluster von Cassandra wird ein Datensatz auf jeweils einem Knoten gehalten. Um bei einem Ausfall eines Cluster-Knotens Informations-Verlust zu verhindern, werden Datensätze auf mehrere Knoten repliziert. Dies wird durch den Replikationsfaktor RF
beschrieben. So werden im folgenden Bild die Daten mit RF=3
abgelegt:
BASE
Schreibt ein Client Daten in den Ring-Cluster und liest beispielsweise ein anderer Client kurz danach die Daten, so können Inkonsistenzen auftreten. Es dauert eine gewisse Zeit, bis alle beteiligten Knoten des Rings alle Datenänderungen mitbekommen haben. Ist so ein Zeitfenster der Inkonsistenz fachlich möglich, so spricht man von einer BASE-Architektur, in der das E für die “Eventual Consistency” steht. “Eventual” ist hier selbstverständlich mit “letztendlich” zu übersetzen; letztendlich wird ein Ring-Cluster einen konsistenten Zustand erreichen.
Tunable Consistency
Wird fachlich Konsistenz gefordert, so kann dies in einem Ring-Cluster dadurch erreicht werden, dass die Antwort des Clients so lange verzögert wird, bis die Daten auf allen replizierten Knoten angekommen sind.
Eine nahe liegende Lösung wäre also, bei einer Schreib-Operation W
zu verlangen, dass RF
Knoten die Daten geschrieben haben.
Dann kann ein Lesevorgang von einem beliebigen Knoten ausgeführt werden.
Also insgesamt:
W = RF
und R = 1
Aber auch “anders herum” wird Konsistenz erreicht:
W = 1
und R = RF
Auf diese Art und Weise kann ausbalanciert werden, ob Wert auf schnelle Schreib- oder auf schnelle Lese-Vorgänge gelegt werden soll. Dies wird als “Tunable Consistency” bezeichnet.
Beide Verfahren haben jedoch den Nachteil, dass bei einem Partitionsfehler, also einem Ausfall der Kommunikation zwischen Knoten, der gesamte Ring-Cluster in einem Standby-Modus geschaltet werden muss und keine Antwort liefern kann. Dies kann vermieden werden, in dem für Schreib und Lesevorgänge das Quorum benutzt wird:
W = R = (RF + 1)/2
Auch hier ist Konsistenz garantiert, allerdings muss nur noch in die Majorität der Knoten geschrieben werden.