In letzter Zeit habe ich viel auf Konferenzen gesprochen, um den Leuten von unserer Möglichkeit zu erzählen, große Neo4j-Datenbanken zu erstellen. Groß bedeutet einige zehn Millionen Knoten und Hunderte von Millionen Beziehungen und Milliarden von Eigenschaften.
Obwohl die technische Beschreibung bereits in Teil 1 und Teil 2 des Xebia-Blogs zu finden ist, möchte ich Ihnen einen funktionelleren Überblick darüber geben, was wir getan haben und warum wir überhaupt damit angefangen haben.
Unser Anwendungsfall bestand darin, unsere Daten zu untersuchen, um interessante Muster zu finden. Bei den Daten, die wir untersuchen möchten, geht es um Finanztransaktionen zwischen Personen, so dass das Neo4j-Graphenmodell gut für uns geeignet ist. Da wir im Vorfeld nicht wissen, wonach wir suchen, müssen wir eine Neo4j-Datenbank mit einigen Teilen der Daten erstellen und diese untersuchen. Wenn es nichts Interessantes zu finden gibt, erweitern wir unsere Daten um neue Informationen und möglicherweise neue Verbindungen und erstellen eine neue Neo4j-Datenbank mit den zusätzlichen Informationen.
Das bedeutet, dass es nicht darum geht, die aktuellen Daten einmalig zu laden und sie durch Hinzufügen weiterer Knoten und Kanten auf dem neuesten Stand zu halten. Es geht vielmehr darum, jedes Mal eine neue Datenbank von Grund auf zu erstellen, wenn uns eine neue Möglichkeit einfällt, die Daten zu betrachten.
Erster Versuch ohne Hadoop
Bevor wir unsere Hadoop-basierte Lösung entwickelt haben, haben wir das Batchimport-Framework von Neo4j (die Batch Inserter API) verwendet. Damit können Sie eine große Anzahl von Knoten und Kanten ohne Transaktions-Overhead einfügen (Neo4j ist ACID-konform). Die Batch-Importer-API eignet sich sehr gut für mittelgroße Graphen oder den einmaligen Import großer Datensätze, aber in unserem Fall, in dem wir mehrere Datenbanken pro Tag neu erstellen, war die Laufzeit zu lang.
Verkleinern
Um den Prozess zu beschleunigen, wollten wir unseren Hadoop-Cluster nutzen. Wenn wir den Prozess der Erstellung einer Neo4j-Datenbank auf verteilte Weise durchführen könnten, könnten wir die Gesamtzahl der Cluster-Maschinen anstelle des Batchimporters auf einer einzelnen Maschine nutzen.
Aber wie gehen Sie dabei vor? Das Batch-Import-Framework basierte auf der Idee, die Daten an einem einzigen Ort zu speichern. Ein Server, der irgendwo läuft, mit dem sich der Cluster verbinden kann, hatte mehrere Nachteile:
- Wie man mit Ausfallzeiten des Neo4j-Servers umgeht
- Sie sind wieder bei der Transaktion angelangt
- Sie müssen prüfen, ob bereits Knoten vorhanden sind
Die Idee war also, die Datenbank wirklich von Grund auf neu aufzubauen. Wäre es möglich, die zugrunde liegende Dateistruktur zu erstellen, ohne dass Neo4j irgendwo laufen muss? Das wäre doch cool, oder?
Also haben wir es getan! Wir untersuchten die interne Dateistruktur (wie sie funktioniert, erfahren Sie in Teil 2 des technischen Blogs) und mussten noch eine weitere Hürde überwinden, damit es wirklich funktioniert.
Wir brauchten monoton ansteigende Zeilen-IDs, weil die Position in einer Neo4j-Datei etwas bedeutet. Die ID des Knotens oder der Beziehung ist direkt mit dem Offset in der Datei verbunden. Wir konnten also nicht einfach ein paar Zahlen als IDs zu unseren Daten hinzufügen, weil es keine Lücke zwischen den Nummerierungen geben durfte. In Frisos Blog über die monoton ansteigenden Zeilen-IDs können Sie nachlesen, wie wir das gemacht haben.
Weitere Informationen finden Sie in unserer Präsentation, der Code ist auf github zu finden, und Sie können uns kontaktieren, wenn Sie mehr wissen möchten.
Unsere Ideen
Weitere Blogs
Contact



