Warum sollten wir diese beiden unterschiedlichen Dinge kombinieren?
Hadoop ist gut für die Datenverarbeitung geeignet, aber die Endergebnisse in flachen Dateien sind für den Kunden nicht sehr ansehnlich. Außerdem ist es schwierig, Ihre Netzwerkdaten in Excel zu visualisieren.
Neo4J ist perfekt für die Arbeit mit unseren vernetzten Daten. Wir verwenden es häufig, um unsere verschiedenen Datensätze zu visualisieren.
Wir bereiten also unseren Datensatz mit Hadoop vor und importieren ihn in Neo4J, die Graphdatenbank, um die Daten abfragen und visualisieren zu können.
Wir haben viele verschiedene Möglichkeiten, unseren Datensatz zu betrachten, so dass wir dazu neigen, alle paar Tage einen neuen Auszug der Daten mit einigen neuen Eigenschaften zu erstellen, um sie zu betrachten.
In diesem Blog geht es darum, wie wir Hadoop und Neo4J kombiniert haben, und wir beschreiben die Phasen, die wir bei unserer Suche nach der optimalen Lösung durchlaufen haben.
So haben wir es also angefangen.
Phase I:
- Verwenden Sie Hive zur Datenaufbereitung. Für diejenigen unter Ihnen, die mit dem Hadoop-Ökosystem nicht vertraut sind: Hive ist ein Tool, mit dem Sie SQL zum Schreiben von Abfragen verwenden können, die in Map/Reduce-Jobs umgewandelt werden. Wir verwenden dies, um aus unseren Daten eine Nodes-Tabelle und eine Edge-Tabelle zu erstellen.
Das Endergebnis dieser Reihe von Abfragen sind zwei Sätze von Dateien, die wir aus unserem Hadoop-Cluster auf unseren lokalen Rechner holen können.
Die Nodes-Tabelle/Datei sieht in etwa so aus:
NodeId Property1 Property2 PropertyN
AAA nameOfA amountOfA someAThing
BBB nameOfB amountOfB someBThing
CCC nameOfC amountOfC someCThing
DDD nameOfD amountOfD someDThing
Die Kanten-Tabelle/Datei sieht in etwa so aus:
fromNodeId ToNodeId EdgeProperty1 EdgePropertyN
AAA BBB someDate1 someNumber1
AAA DDD someDate2 someNumber2
BBB DDD someDate3 someNumber3
CCC BBB someDate4 someNumber4
DDD BBB someDate5 someNumber5
DDD CCC someDate6 someNumber6
- Um diese Datensätze in Neo4J zu laden, verwenden wir den Batchinserter.
Zu der Zeit, als wir unseren ersten Importer erstellten, war die Version von Neo4J etwa 1.6. Also haben wir etwas Code geschrieben und den Import gestartet.
Der Datensatz, um den es hier geht, hat etwa 30 Millionen Knoten mit jeweils 9 Eigenschaften und etwa 650 Millionen Kanten mit jeweils 4 Eigenschaften.
[code lang="java"]
import java.io.BufferedReader;
import java.io.InputStreamReader;
import org.neo4j.kernel.impl.batchinsert.BatchInserter;
import org.neo4j.kernel.impl.batchinsert.BatchInserterImpl;
BatchInserter db = new BatchInserterImpl(<outputPfad>, <Konfiguration>)
long[] idCache = new long[<nrOfNodes>];
BufferedReader reader = new BufferedReader(new InputStreamReader(<InputStreamThingy>), 100 * 1024 *1024)
String-Zeile;
while ((line = reader.readLine()) != null) {
String[] parts = line.split('t');
int myOwnId = Integer.parseInt(parts[0]);
//Einige Eigenschaftsmagie geht hier
idCache[myOwnId] = db.createNode(<EigenschaftenMap>);
}
reader.close();
//Edges
reader = new BufferedReader(newInputStreamReader(<InputStreamThingyforEdges>), 100 * 1024 *1024)
while ((line = reader.readLine()) != null) {
String[] parts = line.split('t');
int fromNodeOwnId = Integer.parseInt(parts[0]);
int toNodeOwnId = Integer.parseInt(parts[1]);
//Einige Eigenschaftsmagie geht hier
db.createRelationship(idCache[fromNodeOwnId], idCache[toNodeOwnId], <RelationshipType>, <EigenschaftenMap>);
}
reader.close();
[/code]
- Wir importieren diese Knoten und Kanten auf unserem Desktop-Rechner mit 16 GB RAM, was etwa 20 Stunden in Anspruch nimmt.
Phase II:
Wir müssen also die Dinge ein wenig beschleunigen. In dieser Phase entfernen wir den Teil, in dem wir die Nodes- und Edges-Dateien von unserem Hadoop-Cluster auf unseren lokalen Rechner holen und lesen sie direkt aus dem Cluster.
- Verwenden Sie weiterhin Hive, um die Daten vorzubereiten
- Lassen Sie den Importer die Dateien direkt aus dem Cluster lesen (keine Kopie mehr erforderlich)
[code lang="java"]
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
FileSystem fs = FileSystem.get(<hadoop configuration>);
FileStatus[] files = fs.globStatus(new Path(<pathToNodesTableOrFile>));
for (FileStatus file : files) {
DataInputStream dis = new DataInputstream(fs.open(file.getPath()));
BufferedReader reader = new BufferedReader(new InputStreamReader(dis), 100 * 1024 * 1024);
while ((line = reader.readLine()) != null) {
}
}
[/code]
- Führen Sie den Importer auf einem der Worker Nodes des Hadoop-Clusters (mit 32 GB) aus (stellen Sie sicher, dass keine Hadoop-Prozesse laufen, damit wir die vollen 32 GB nutzen können).
Dies dauert etwa 16 Stunden, und wir müssen die Daten von diesem Rechner auf den Rechner übertragen, auf dem die Neo4J-Datenbank läuft (dies dauerte etwa 2 Stunden für etwa 80 GB).
Phase III:
Wir haben nur eine sehr geringe Verbesserung der Gesamtzeit für die Erstellung der vollständigen Neo4J-Datenbank erreicht, so dass wir noch mehr ausprobieren mussten.
Auf der Mailingliste gab es einige Gerüchte, dass die aktuelle Version von Neo4J (1.8) einige wesentliche Verbesserungen in der Leistung des BatchInserters aufweist
Also haben wir den Importer-Code aktualisiert, um die Version 1.8 von Neo4J (war 1.6) zu verwenden
Die einzige Codeänderung in unserem eigenen Code war die Art und Weise, wie wir die BatchInserter-Klasse erstellen. Andere Optimierungen befinden sich innerhalb des Neo4J-Codes, hauptsächlich in der Art und Weise, wie das Paging-Subsystem im PersistenceWindowPool funktioniert.
[code lang="java"]
import org.neo4j.unsafe.batchinsert.BatchInserter;
import org.neo4j.unsafe.batchinsert.BatchInserters;
BatchInserter db = BatchInserters.inserter(<outputPath>, <config> )
[/code]
- Verwenden Sie immer noch Hive, um die Daten vorzubereiten
- Führen Sie den Importer auf einem der Arbeiterknoten des Hadoop-Clusters aus
dauert etwa 3 Stunden und wir müssen die Daten von diesem Rechner auf den Rechner bringen, auf dem wir die Neo4J-Datenbank laufen lassen (dauerte etwa 2 Stunden für etwa 80 GB)
So weit sind wir jetzt. Aber wir haben noch etwas in petto.
Während wir darauf warteten, dass diese Importe abgeschlossen werden, beschlossen wir zu prüfen, ob wir den Batchimporter auf verteilte Weise arbeiten lassen können, so dass wir unseren 16-Knoten-Hadoop-Cluster nutzen können, um die Neo4J-Erstdatenbank schneller zu erstellen.
Im nächsten Blog werde ich auf die Details dieser Aufgabe eingehen Verfasst von
Kris Geusebroek
Unsere Ideen
Weitere Blogs
Contact
Let’s discuss how we can support your journey.



