Das SparkOnHBase-Projekt in Cloudera Labs wurde kürzlich mit dem Apache HBase-Trunk zusammengeführt. Erfahren Sie in diesem Beitrag die Geschichte des Projekts und wie die Zukunft für das neue HBase-Spark-Modul aussieht.
SparkOnHBase wurde erstmals im Juli 2014 auf Github gepusht, nur sechs Monate nach dem Spark Summit 2013 und fünf Monate nachdem Apache Spark zum ersten Mal in CDH ausgeliefert wurde. Diese Konferenz war ein großer Wendepunkt für mich, denn zum ersten Mal wurde mir klar, dass die MapReduce-Engine einen sehr starken Konkurrenten hatte. Spark stand kurz davor, in eine aufregende neue Phase seines Open-Source-Lebenszyklus einzutreten, und nur ein Jahr später wird es in großem Umfang von Hunderten, wenn nicht Tausenden von Unternehmen verwendet (wovon über 200 auf der Cloudera-Plattform).
SparkOnHBase entstand aus einer einfachen Kundenanfrage heraus, um ein Interaktionsniveau zwischen HBase und Spark zu haben, das dem ähnelt, das bereits zwischen HBase und MapReduce verfügbar ist. Hier ist eine kurze Zusammenfassung der Funktionalität, die im Umfang enthalten war:
- Voller Zugriff auf HBase in einer Karte oder Stufe reduzieren
- Möglichkeit zum Massenladen
- Fähigkeit, Massenoperationen wie Get, Put, Delete auszuführen
- Fähigkeit, eine Datenquelle für SQL-Engines zu sein
Die erste Version von SparkOnHBase wurde für einen Cloudera-Kunden erstellt, der zugestimmt hatte, die Veröffentlichung der Arbeit zuzulassen. Glücklicherweise bekam ich frühzeitig Hilfe von anderen Clouderanern und HBase PMC-Mitgliedern Jon Hsieh und Matteo Bertozzi sowie Spark PMC-Mitglied Tathagata Das, um sicherzustellen, dass das Design sowohl für Basis-Apache Spark als auch für Spark Streaming funktioniert.
Es dauerte nicht lange, bis andere Kunden anfingen, SparkOnHBase zu verwenden – allen voran Edmunds.com mit seiner Echtzeit-Spark-Streaming-Anwendung für den Super Bowl-Sonntag. Als andere Unternehmen an Bord sprangen, wurde schnell klar, dass ein einzelner Projektbetreuer (nämlich ich) nicht skalieren würde. Glücklicherweise hatte Cloudera zu diesem Zeitpunkt kürzlich Cloudera Labs angekündigt, das sich als perfekte Heimat für das Projekt herausstellte. Einfach gesagt, Cloudera Labs ist ein virtueller Container für aufstrebende Ökosystemprojekte, die in Bezug auf ihre Unternehmensbereitschaft, Entwicklung und ihren Ehrgeiz jung sind, aber von Benutzern, die die neuesten Technologien ausprobieren möchten, sehr gefragt sind. SparkOnHBase wurde zu gegebener Zeit ein Cloudera Labs-Projekt.
Heute freue ich mich, Ihnen mitteilen zu können, dass SparkOnHBase kürzlich dem HBase-Trunk (HBASE-13992) zugewiesen wurde. HBASE-13992 fügt SparkOnHBase dem HBase-Kern unter einem neuen Spitznamen, dem HBase-Spark-Modul, hinzu. Ich möchte Andrew Purtell, Vizepräsident von HBase, für seine Ermutigung und sein „Türöffnen“ für HBASE-13992 und PMC-Mitglied Sean Busbey für sein Mentoring und seine Anleitung danken. Außerdem möchte ich Elliott Clark, Enis Soztutar, Michael Stack, Nicolas Liochon, Kostas Sakellis, Ted Yu, Lars Hofhansl und Steve Loughran für ihre Code-Reviews danken. (Wie Sie sehen können, war SparkOnHBase eine echte Gemeinschaftsleistung.)
Insbesondere konnte ich mit HBASE-13992 zum ersten Mal überhaupt Spark- und Scala-Code zum Apache HBase-Projekt hinzufügen. Es hat super viel Spaß gemacht, das Privileg zu haben, den ersten Scala-Einheitentest in der Geschichte von HBase zu erstellen!
Kommen wir nun zu den technischen Details.
In HBASE-13992
In HBASE-13992 werden Sie sehen, dass der Großteil des ursprünglichen Codes und Designs von SparkOnHBase unverändert bleibt. Die grundlegende Architektur bleibt bestehen, da der Kernteil des Codes darauf ausgelegt ist, ein HBase-Verbindungsobjekt in jedem Spark-Executor zu erhalten.
Während die Grundlagen bestehen bleiben, gibt es drei Hauptunterschiede zwischen dem HBASE-13992-Patch und dem SparkOnHBase-Projekt von Cloudera Labs:
- HBase-APIs: HBASE-13992 verwendet durchgehend alle neuen HBase 1.0+ APIs.
- RDD- und DStream-Funktionen: Eine der größten Beschwerden über SparkOnHBase bezog sich darauf, wie Funktionen ausgeführt wurden; Spark-Liebhaber wollten HBase-Aktionen direkt von einem RDD oder DStream ausführen. In HBASE-13992 ist diese Fähigkeit über Komponententests und Beispiele integriert. Darüber hinaus gibt es später in diesem Beitrag Codebeispiele für HBase-Funktionen direkt aus RDDs, damit Sie ein Gefühl dafür bekommen, wie die APIs aussehen werden.
- Einfache
foreach
undmap
Funktionen: Jetzt ist es noch einfacher,foreachPartition
auszuführen s undmapPartition
s mit einer HBase-Verbindung. Ein Beispiel folgt später in diesem Beitrag.
Nehmen wir uns jetzt eine kurze Minute Zeit und gehen die Unterschiede zwischen der SparkOnHBase-Codebasis und dem HBASE-13992-Patch durch. Hier ist ein kurzes Beispiel für bulkDelete
von SparkOnHBase:
val hbaseContext = new HBaseContext(sc, config); hbaseContext.bulkDelete[Array[Byte]](rdd, tableName, putRecord => new Delete(putRecord), 4);
Beachten Sie, dass wir in diesem Beispiel eine Funktion direkt vom HBaseContext-Objekt aufrufen, obwohl die Operation wirklich auf dem RDD ausgeführt wurde. Sehen wir uns nun das HBase-Spark-Modul für denselben Code an:
val hbaseContext = new HBaseContext(sc, config) rdd.hbaseBulkDelete(hbaseContext, tableName, putRecord => new Delete(putRecord), 4)
Der große Unterschied besteht darin, dass hbaseBulkDelete
Methode kommt direkt aus dem RDD. Außerdem lässt dieser Ansatz die Tür für die folgenden Optionen mit einem zukünftigen JIRA offen:
val hbaseContext = new HBaseContext(sc, config) rdd.hbaseBulkDelete(tableName)
Das ist im Moment so sauber, wie ich es bekommen kann, aber das Ziel ist es, es noch mehr zu machen einfach und sauber.
Werfen wir auch einen kurzen Blick auf die Funktionen foreach und map in HBASE-13992. Sie können in der ForeachPartition
sehen Beispiel unten, dass wir einen Iterator und eine HBase Connection
haben Objekt. Dies gibt uns die volle Macht, alles mit HBase zu tun, während wir unsere Werte durchlaufen:
val hbaseContext = new HBaseContext(sc, config) rdd.hbaseForeachPartition(hbaseContext, (it, conn) => { val bufferedMutator = conn.getBufferedMutator(TableName.valueOf("t1")) ... bufferedMutator.flush() bufferedMutator.close() })
Schließlich ist hier ein Beispiel für eine Zuordnungspartitionsfunktion, bei der wir ein Verbindungsobjekt erhalten können, wenn wir unsere Werte durchlaufen:
val getRdd = rdd.hbaseMapPartitions(hbaseContext, (it, conn) => { val table = conn.getTable(TableName.valueOf("t1")) var res = mutable.MutableList[String]() ... })
Zukunftsarbeit
Die folgenden JIRAs stehen auf meiner TO DO-Liste:
HBASE-14150 – BulkLoad
hinzufügen Funktionalität zum HBase-Spark-Modul
Bald werden wir in der Lage sein, Massenladungen direkt aus RDDs mit Code durchzuführen, der so einfach aussieht wie:
rdd.hbaseBulkLoad (tableName, t => { Seq((new KeyFamilyQualifier(t.rowKey, t.family, t.qualifier), t.value)). iterator }, stagingFolder)
HBASE-14181 – Spark DataFrame-Datenquelle zum HBase-Spark-Modul hinzugefügt
Mit diesem Patch können wir Spark SQL direkt in HBase integrieren und coole Dinge wie Filter- und Spaltenauswahl-Pushdown sowie Scan-Range-Pushdown ausführen. Das Ziel der Interaktion von Spark SQL und HBase ist so einfach wie das Folgende:
val df = sqlContext.load("org.apache.hadoop.hbase.spark", Map("hbase.columns.mapping" -> "KEY_FIELD STRING :key, A_FIELD STRING c:a, B_FIELD STRING c:b,", "hbase.table" -> "t1")) df.registerTempTable("hbaseTmp") sqlContext.sql("SELECT KEY_FIELD FROM hbaseTmp " + "WHERE " + "(KEY_FIELD = 'get1' and B_FIELD < '3') or " + "(KEY_FIELD <= 'get3' and B_FIELD = '8')").foreach(r => println(" - " + r))
Es gibt andere JIRAs, die den Code benutzerfreundlicher und den Komponententest umfassender machen sollen. Mein persönliches Ziel ist es, in einem Folge-Blogbeitrag über all die großartigen Fortschritte berichten zu können, die wir machen. Ziel ist es, Spark zu dem erstklassigen Bürger zu machen, der es in Bezug auf HBase verdient, und es als MapReduce-Ersatz in der Branche weiter zu festigen. Durch das Ersetzen von MapReduce durch Spark können wir noch mehr Verarbeitung auf HBase-Clustern durchführen, ohne dass wir uns Sorgen machen müssen, dass es zu mehr Platten-E/A-Konflikten kommt.
Es wird einige Zeit dauern, bis das HBase-Spark-Modul in eine Version von HBase aufgenommen wird. In der Zwischenzeit gibt es Pläne, einen Teil des Codes aus dem HBase-Spark-Modul in SparkOnHBase in Cloudera Labs zurückzuportieren. Derzeit funktioniert SparkOnHBase auf CDH 5.3 und 5.4, und das Ziel wird sein, SparkOnHBase mit den Fortschritten des HBase-Spark-Moduls für die kommende CDH-Nebenversion später im Jahr 2015 zu aktualisieren.
Ted Malaska ist Lösungsarchitekt bei Cloudera, Mitwirkender bei Spark, Apache Flume und Apache HBase und Co-Autor des O'Reilly-Buchs Hadoop-Anwendungsarchitekturen.