Pig und HBase mit Lucidworks Big Data
Eines der Ziele von Lucidworks Big Data (LWBD) ist es, die Zusammenarbeit von Komponenten innerhalb des Hadoop-Ökosystems zu erleichtern. Ein Weg, den wir in LWBD häufig nutzen, ist das Lesen und Schreiben von Daten in HBase über Pig. Auf der einfachsten Ebene wird dies durch das von Pig bereitgestellte HBaseStorage Load/Store Backend ermöglicht. Wir haben festgestellt, dass die Art und Weise, wie HBaseStorage Datensätze zurückgibt, und die Art und Weise, wie Pig Daten manipuliert, nicht ganz übereinstimmen. Insbesondere gibt HBaseStorage assoziative Arrays (Maps) zurück, die den Spalten entsprechen. Pig ist jedoch sehr datensatzorientiert und bietet keine Unterstützung für die Manipulation von Maps.
Um dieses Problem zu lösen, haben wir eine einfache Pig UDF (User Defined Function) namens AddToMap geschrieben, die eine Map mit einem oder mehreren Schlüssel-Wert-Paaren hinzufügt oder aktualisiert. Sehen wir sie uns in Aktion an.
Lassen Sie uns zunächst zwei Textdateien definieren:
text1.txt
1, Sammlung1, Datensatz Eins 2, Sammlung1, Datensatz Zwei |
text2.txt
1, extra, Einige zusätzliche Daten für id=1 1, foo, bar |
Wir lesen die erste Textdatei ein und verwenden die integrierte TOMAP-Funktion, um eine Map zu erstellen, die wir in einer Spaltenfamilie „cf1“ in HBase speichern.
– Laden aus einer Textdatei A = load ‚text1.txt‘ using PigStorage(‚,‘) as (id:chararray, collection:chararray, title:chararray); – Zuordnen der Felder zu einem einzelnen map[]-Feld – Speichern in HBase |
Wenn wir „test-table“ in HBase scannen, sehen wir:
hbase(main):003:0> scan ‚test-table‘ ROW COLUMN+CELL 1 column=cf1:collection, timestamp=1361806763289, value=Record One 1 column=cf1:title, timestamp=1361806763289, value=Record One 2 column=cf1:collection, timestamp=1361806763290, value=Record Two 2 column=cf1:title, timestamp=1361806763290, value=Record Two |
Jetzt lesen wir diese Datensätze aus HBase, lesen die zweite Textdatei, fügen die beiden zusammen und aktualisieren unsere bestehenden Datensätze in HBase
– Laden aus HBase C = load ‚hbase://test-table‘ using org.apache.pig.backend.hadoop.hbase.HBaseStorage(‚cf1, cf2‘, ‚-loadKey true‘) as (rowkey:bytearray, cf1:map[], cf2:map[]); – Laden Sie eine weitere Textdatei und verbinden Sie sie mit unseren Daten – Speichern in HBase |
Hier laden wir zwei Spaltenfamilien in Maps, obwohl nur „cf1“ Daten enthält (hauptsächlich, um die Syntax für mehrere Spaltenfamilien zu demonstrieren). Das Flag „loadKey“ zeigt an, dass Sie den Zeilenschlüssel als Feld in Pig aufnehmen möchten (es ist das 1. Feld und hat den Typ Bytearray).
Das Interessante daran ist, dass wir die Relation „F“ erstellen. Hier verwenden wir die AddToMap UDF, um unsere „cf1“-Map zu ändern, die dann auf einzelne Spalten in HBase abgebildet wird. AddToMap ermöglicht diese Art von Lese-, Änderungs- und Schreibvorgängen.
Wenn wir „test-table“ erneut scannen, sehen wir jetzt die neuen Felder:
hbase(main):004:0> scan ‚test-table‘ ROW COLUMN+CELL 1 column=cf1:collection, timestamp=1361815334160, value=collection1 1 column=cf1:extra, timestamp=1361815334160, value=Some additional data for id=1 1 column=cf1:foo, timestamp=1361815334160, value=bar 1 column=cf1:title, timestamp=1361815334160, value=Record One 2 column=cf1:collection, timestamp=1361815309532, value=collection1 2 column=cf1:title, timestamp=1361815309532, value=Record Two |
Die gleiche Technik lässt sich auch auf das Lesen und Schreiben von Dokumenten im Dokumentendienst von LWBD anwenden. Der Hauptunterschied besteht darin, dass wir in HBase komplexe Zeilenschlüssel für effiziente Suchvorgänge verwenden. Um unsere benutzerdefinierten Zeilenschlüssel zu kodieren/dekodieren, haben wir zwei UDFs bereitgestellt: ToDocumentRowKey und FromDocumentRowKey. Diese UDFs wandeln die nicht von Menschen lesbaren Zeilenschlüssel in ein Tupel aus (collection, id) um, damit sie in Pig bequem bearbeitet werden können.
Mit HBase haben Sie schnellen wahlfreien Zugriff auf Ihre Daten und mit Pig können Sie ganz einfach heterogene Datensätze verarbeiten. Diese Brücke zwischen den beiden legt den Grundstein für eine sehr leistungsfähige Big-Data-Verarbeitungspipeline.