Le projet SparkOnHBase de Cloudera Labs a récemment été fusionné avec le tronc Apache HBase. Dans cet article, découvrez l'historique du projet et à quoi ressemble l'avenir du nouveau module HBase-Spark.
SparkOnHBase a été poussé pour la première fois vers Github en juillet 2014, six mois seulement après le Spark Summit 2013 et cinq mois après la première expédition d'Apache Spark dans CDH. Cette conférence a été un grand tournant pour moi, car pour la première fois j'ai réalisé que le moteur MapReduce avait un concurrent très sérieux. Spark était sur le point d'entrer dans une nouvelle phase passionnante de son cycle de vie open source, et à peine un an plus tard, il est utilisé à grande échelle dans des centaines, voire des milliers d'entreprises (dont plus de 200 le font sur la plate-forme Cloudera).
SparkOnHBase est né d'une simple demande client d'avoir un niveau d'interaction entre HBase et Spark similaire à celui déjà disponible entre HBase et MapReduce. Voici un bref résumé des fonctionnalités concernées :
- Accès complet à HBase dans une carte ou une étape réduite
- Possibilité d'effectuer un chargement groupé
- Possibilité d'effectuer des opérations groupées telles que get, put, delete
- Capacité à être une source de données pour les moteurs SQL
La version initiale de SparkOnHBase a été conçue pour un client Cloudera qui avait accepté de rendre le travail public. Heureusement, j'ai obtenu l'aide des autres Clouderans et des membres de HBase PMC, Jon Hsieh et Matteo Bertozzi, et du membre de Spark PMC, Tathagata Das, pour m'assurer que la conception fonctionnerait à la fois pour Apache Spark de base et pour Spark Streaming.
Il ne fallut pas longtemps avant que d'autres clients commencent à utiliser SparkOnHBase, notamment Edmunds.com avec son application Spark Streaming en temps réel pour le Super Bowl Sunday. Lorsque d'autres entreprises ont sauté à bord, il est rapidement devenu clair qu'un seul responsable de projet (à savoir:moi) n'allait pas évoluer. Heureusement, à cette époque, Cloudera avait récemment annoncé Cloudera Labs, qui s'est avéré être le lieu idéal pour le projet. En termes simples, Cloudera Labs est un conteneur virtuel pour les projets d'écosystème émergents qui sont jeunes en termes de préparation, de développement et d'ambition d'entreprise, mais qui sont très demandés par les utilisateurs qui souhaitent essayer les dernières technologies. SparkOnHBase est devenu un projet Cloudera Labs en temps voulu.
Aujourd'hui, je suis heureux d'annoncer que SparkOnHBase a récemment été engagé dans le tronc HBase (HBASE-13992). HBASE-13992 ajoute SparkOnHBase au noyau HBase sous un nouveau surnom, le module HBase-Spark. Je tiens à remercier le vice-président de HBase, Andrew Purtell, pour ses encouragements et son "ouverture de la porte" pour HBASE-13992 et le membre de PMC, Sean Busbey, pour son mentorat et ses conseils. Je tiens également à remercier Elliott Clark, Enis Soztutar, Michael Stack, Nicolas Liochon, Kostas Sakellis, Ted Yu, Lars Hofhansl et Steve Loughran pour leurs révisions de code. (Comme vous pouvez le voir, SparkOnHBase était un authentique effort communautaire.)
Notamment, avec HBASE-13992, j'ai pu ajouter du code Spark et Scala au projet Apache HBase pour la toute première fois. C'était super amusant d'avoir le privilège de créer le premier test unitaire Scala de l'histoire de HBase !
Passons maintenant aux détails techniques.
À l'intérieur de HBASE-13992
Dans HBASE-13992, vous verrez que la plupart du code et de la conception d'origine de SparkOnHBase restent inchangés. L'architecture de base tient toujours, dans la mesure où la partie centrale du code est conçue pour obtenir un objet de connexion HBase dans chaque exécuteur Spark.
Bien que les bases demeurent, il existe trois différences majeures entre le correctif HBASE-13992 et le projet Cloudera Labs SparkOnHBase :
- API HBase : HBASE-13992 utilise toutes les nouvelles API HBase 1.0+ partout.
- Fonctions RDD et DStream : L'une des plus grandes plaintes concernant SparkOnHBase concernait la façon dont les fonctions étaient exécutées ; Les amateurs de Spark voulaient créer des actions HBase directement à partir d'un RDD ou DStream. Dans HBASE-13992, cette fonctionnalité est intégrée via des tests unitaires et des exemples. De plus, vous trouverez des exemples de code de fonctions HBase directement à partir des RDD plus loin dans cet article, afin que vous puissiez avoir une idée de ce à quoi ressembleront les API.
foreach
facile etmap
fonctions : Maintenant, il est encore plus facile de faireforeachPartition
s etmapPartition
s avec une connexion HBase. Un exemple suivra plus tard dans cet article.
Maintenant, prenons une petite minute et parcourons les différences entre la base de code SparkOnHBase et le correctif HBASE-13992. Voici un exemple rapide de bulkDelete
depuis SparkOnHBase :
val hbaseContext = new HBaseContext(sc, config); hbaseContext.bulkDelete[Array[Byte]](rdd, tableName, putRecord => new Delete(putRecord), 4);
Notez que dans cet exemple, nous appelons une fonction directement à partir de l'objet HBaseContext, même si l'opération était réellement exécutée sur le RDD. Regardons maintenant le module HBase-Spark pour le même code :
val hbaseContext = new HBaseContext(sc, config) rdd.hbaseBulkDelete(hbaseContext, tableName, putRecord => new Delete(putRecord), 4)
La grande différence est que le hbaseBulkDelete
méthode vient tout droit du RDD. Aussi, cette approche laisse la porte ouverte aux options suivantes avec un futur JIRA :
val hbaseContext = new HBaseContext(sc, config) rdd.hbaseBulkDelete(tableName)
C'est aussi propre que possible pour le moment, mais le but est de le rendre encore plus simple et propre.
Jetons également un coup d'œil aux fonctions foreach et map dans HBASE-13992. Vous pouvez voir dans le ForeachPartition
exemple ci-dessous que nous avons un itérateur et une Connection
HBase objet. Cela nous donnera tout le pouvoir de faire n'importe quoi avec HBase pendant que nous itérons sur nos valeurs :
val hbaseContext = new HBaseContext(sc, config) rdd.hbaseForeachPartition(hbaseContext, (it, conn) => { val bufferedMutator = conn.getBufferedMutator(TableName.valueOf("t1")) ... bufferedMutator.flush() bufferedMutator.close() })
Enfin, voici un exemple de fonction de partition de carte où nous pouvons obtenir un objet de connexion lorsque nous parcourons nos valeurs :
val getRdd = rdd.hbaseMapPartitions(hbaseContext, (it, conn) => { val table = conn.getTable(TableName.valueOf("t1")) var res = mutable.MutableList[String]() ... })
Travail futur
Les JIRA suivants sont sur ma liste de choses à faire :
HBASE-14150 – Ajouter BulkLoad
fonctionnalité du module HBase-Spark
Bientôt, nous pourrons effectuer des chargements en masse directement à partir des RDD avec un code aussi simple que :
rdd.hbaseBulkLoad (tableName, t => { Seq((new KeyFamilyQualifier(t.rowKey, t.family, t.qualifier), t.value)). iterator }, stagingFolder)
HBASE-14181 – Ajouter une source de données Spark DataFrame au module HBase-Spark
Avec ce correctif, nous serons en mesure d'intégrer directement Spark SQL à HBase et de faire des choses intéressantes comme le refoulement de la sélection de filtres et de colonnes, ainsi que le refoulement de la plage d'analyse. L'objectif d'obtenir une interaction Spark SQL et HBase est aussi simple que le suivant :
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))
Il existe d'autres JIRA conçus pour rendre le code plus facile à utiliser et rendre le test unitaire plus complet. Mon objectif personnel est de pouvoir rendre compte dans un article de blog de suivi de tous les grands progrès que nous réalisons. L'objectif est de faire de Spark le citoyen de première classe qu'il mérite d'être en ce qui concerne HBase, en le solidifiant davantage en tant que remplaçant de MapReduce dans l'industrie. Le remplacement de MapReduce par Spark nous permettra d'effectuer encore plus de traitement sur les clusters HBase, sans ajouter de crainte qu'il y ait plus de conflits d'E/S disque.
Il faudra du temps avant que le module HBase-Spark ne devienne une version de HBase. En attendant, il est prévu de rétroporter une partie du code du module HBase-Spark vers SparkOnHBase dans Cloudera Labs. Actuellement, SparkOnHBase fonctionne sur CDH 5.3 et 5.4, et l'objectif sera de mettre à jour SparkOnHBase avec les avancées du module HBase-Spark pour la prochaine version mineure de CDH plus tard en 2015.
Ted Malaska est architecte de solutions chez Cloudera, contributeur à Spark, Apache Flume et Apache HBase, et co-auteur du livre O'Reilly, Architectures d'applications Hadoop.