Effiziente Modellierung versionierter Hierarchien in Cassandra

9

Haftungsausschluss:
Das ist ein ziemlich langer Post. Ich erkläre zuerst die Daten, mit denen ich es zu tun habe, und was ich damit machen will.
Dann beschreibe ich drei mögliche Lösungen, die ich in Betracht gezogen habe, weil ich versucht habe, meine Hausaufgaben zu machen (ich schwöre:]). Ich habe am Ende eine "beste Schätzung", die eine Variation der ersten Lösung ist.

Meine letzte Frage ist: Was ist der vernünftigste Weg, um mein Problem mit Cassandra zu lösen? Ist es einer meiner Versuche, oder ist es etwas anderes? Ich suche Rat / Feedback von erfahrenen Cassandra-Benutzern ...

Meine Daten:
Ich habe viele SuperDocuments, die Dokumente in einer Baumstruktur besitzen (Überschriften, Zwischenüberschriften, Abschnitte, ...).

Jede SuperDocument-Struktur kann sich im Laufe der Zeit ändern (meistens umbenennen), was mir mehrere Versionen der Struktur gibt, wie unten gezeigt.

Was ich suche:
Für jedes SuperDocument muss ich diese Strukturen nach Datum wie oben mit Zeitstempel versehen und möchte zu einem bestimmten Zeitpunkt die nächstliegende frühere Version der SuperDocument-Struktur finden. (dh die neueste Version, für die version_date < given_date gilt)

Diese Überlegungen könnten helfen, das Problem leichter zu lösen:

  • Versionen sind unveränderlich: Änderungen sind selten genug, ich kann bei jeder Änderung eine neue Repräsentation der gesamten Struktur erstellen.
  • Ich muss nicht auf einen Teilbaum der Struktur zugreifen.
  • Ich würde sagen, dass es in Ordnung ist zu sagen, dass ich nicht alle Vorfahren eines bestimmten Blattes finden muss, noch muss ich auf einen bestimmten Knoten / Blatt innerhalb des Baumes zugreifen. Ich kann das alles in meinem Clientcode bearbeiten, sobald ich den ganzen Baum habe.

OK, lasst es uns tun
Bitte denkt daran, ich fange gerade erst an, Cassandra zu benutzen. Ich habe viele Ressourcen zur Datenmodellierung gelesen / angeschaut, aber ich habe nicht viel Erfahrung (!) In diesem Bereich!
Was bedeutet auch, dass alles in CQL3 geschrieben wird ... sorry Thrift Liebhaber!

Mein erster Versuch, dies zu lösen, war die folgende Tabelle zu erstellen:

%Vor%

Das würde mir die folgende Struktur geben:

Ich verwende hier ein Modell für verschachtelte Sets für meine Bäume. Ich dachte, es würde gut funktionieren, um die Struktur geordnet zu halten, aber ich bin offen für andere Vorschläge.

Ich mag diese Lösung: Jede Version hat ihre eigene Zeile, in der jede Spalte eine Ebene der Hierarchie darstellt.
Das Problem ist jedoch, dass ich (ehrlich gesagt) meine Daten wie folgt abfragen wollte:

%Vor%

Cassandra hat mich schnell daran erinnert, dass ich das nicht tun durfte! (Da der Partitionierer die Zeilenreihenfolge auf den Cluster-Knoten nicht beibehält, ist es nicht möglich, über Partitionsschlüssel zu scannen)

Was dann ...?
Nun, weil Cassandra mich nicht zulassen wird, Ungleichungen auf Partitionsschlüsseln zu verwenden, also sei es! Ich mache version_date zu einem Clustering-Schlüssel und alle meine Probleme werden weg sein. Ja, nicht wirklich ...

Erster Versuch:

%Vor%

Ich finde das eine weniger elegant: Alle Versionen und Strukturstufen werden in Spalten einer jetzt sehr breiten Reihe (im Vergleich zu meiner vorherigen Lösung) gemacht:

Problem: Mit der gleichen Anfrage wird mit LIMIT 1 nur die erste Überschrift zurückgegeben. Und die Verwendung von LIMIT würde alle Versionsstrukturen zurückgeben, die ich filtern müsste, um nur die neuesten zu behalten.

Zweiter Versuch:

es gibt noch keinen zweiten Versuch ... Ich habe zwar eine Idee, aber ich denke, es benutzt Cassandra nicht weise.

Die Idee wäre, nur nach version_date zu clustern, und irgendwie ganze Hierarchien in jeder Spalte zu speichern. Klingt schlecht, nicht wahr?

Ich würde so etwas tun:

%Vor%

Die resultierende Zeilenstruktur wäre dann:

Es sieht für mich in der Tat gut aus, aber ich werde wahrscheinlich mehr Daten haben als der Level-Titel, um mich in meine Spalten zu normalisieren. Wenn es nur zwei Attribute sind, könnte ich mit einer anderen Karte gehen (zum Beispiel Titel mit IDs assoziieren), aber mehr Daten würden zu mehr Listen führen, und ich habe das Gefühl, dass es schnell zu einem Anti-Pattern werden würde Außerdem müsste ich alle Listen in meiner Client-App zusammenführen, wenn die Daten eintreffen!

ALTERNATIVE & amp; BESTER GUESS
Nachdem wir uns einige Gedanken gemacht haben, gibt es eine "hybride" Lösung, die funktionieren könnte und effizient und elegant sein könnte:

Ich könnte eine andere Tabelle verwenden, die nur die Versionsdaten eines SuperDocuments & amp; cache diese Daten in eine Memcache-Instanz (oder Redis oder was auch immer) für einen wirklich schnellen Zugriff.
Das würde es mir ermöglichen, schnell die Version zu finden, die ich abrufen muss, und sie dann unter Verwendung des zusammengesetzten Schlüssels meiner ersten Lösung anzufordern.

Das sind zwei Abfragen sowie ein Speicher-Cache-Speicher zum Verwalten.Aber ich könnte trotzdem mit einem enden, also wäre das vielleicht der beste Kompromiss? Vielleicht brauche ich nicht einmal einen Cache-Speicher?

Alles in allem glaube ich, dass die erste Lösung die eleganteste ist, um meine Daten zu modellieren. Was ist mit dir?!

    
Olivier Lance 22.08.2014, 14:40
quelle

1 Antwort

3

Zuerst müssen Sie weder memcache noch redis verwenden. Cassandra wird Ihnen sehr schnellen Zugriff auf diese Informationen geben. Sie könnten sicherlich einen Tisch haben, der so etwas wie:

%Vor%

, mit dem Sie schnell auf eine bestimmte Version zugreifen können (diese Abfrage mag Ihnen bekannt vorkommen; -):

%Vor%

Da die Struktur des Dokumentenbaums aus der Sicht des Schemas nicht relevant ist und Sie froh sind, das Dokument bei jeder neuen Version vollständig zu erstellen, sehe ich nicht, warum Sie es tun Ich würde sogar den Baum ausreißen, um die Reihen zu trennen. Warum haben Sie nicht einfach das gesamte Dokument in der Tabelle als Text- oder Blobfeld?

%Vor%

Um den Inhalt des Dokuments wie im neuen Jahr zu erhalten, müssen Sie Folgendes tun:

%Vor%

Wenn Sie nun eine Art Hierarchie der Dokumentkomponenten beibehalten möchten, empfehle ich Ihnen, etwas wie Verschlusstabelle Tabelle, um es darzustellen. Alternativ, da Sie bereit sind, das gesamte Dokument auf jeden Schreibvorgang trotzdem zu kopieren, warum kopieren Sie nicht die gesamte Abschnittsinfo zu jedem Schreibvorgang, warum tun Sie das nicht und haben ein Schema wie:

%Vor%

Dann haben Abschnittspfad eine Syntax wie "first_level next_level sub_level leaf_name". Als Nebeneffekt, wenn Sie das version_date des Dokuments haben (oder wenn Sie einen sekundären Index auf section_path erstellen), da ein Leerzeichen lexikalisch "niedriger" ist als jedes andere gültige Zeichen, können Sie einen Unterabschnitt sehr sauber abrufen:

%Vor%

Alternativ können Sie die Abschnitte mit der Unterstützung von Cassandra für Sammlungen speichern, aber noch einmal ... Ich bin mir nicht sicher, warum Sie sie überhaupt aus dem Weg räumen sollten, da es ein großer Brocken funktioniert.

    
Christopher Smith 23.08.2014, 05:07
quelle