O projeto SparkOnHBase no Cloudera Labs foi recentemente integrado ao tronco do Apache HBase. Neste post, conheça a história do projeto e como será o futuro do novo módulo HBase-Spark.
O SparkOnHBase foi lançado pela primeira vez no Github em julho de 2014, apenas seis meses após o Spark Summit 2013 e cinco meses após o lançamento do Apache Spark no CDH. Essa conferência foi um grande ponto de virada para mim, porque pela primeira vez percebi que o mecanismo MapReduce tinha um concorrente muito forte. O Spark estava prestes a entrar em uma nova fase empolgante em seu ciclo de vida de código aberto e, apenas um ano depois, é usado em grande escala em 100, se não 1000, de empresas (com mais de 200 delas fazendo isso na plataforma da Cloudera).
O SparkOnHBase surgiu de uma simples solicitação do cliente para ter um nível de interação entre HBase e Spark semelhante ao já disponível entre HBase e MapReduce. Aqui está um breve resumo da funcionalidade que estava no escopo:
- Acesso total ao HBase em um mapa ou estágio de redução
- Capacidade de fazer um carregamento em massa
- Capacidade de fazer operações em massa como obter, colocar, excluir
- Capacidade de ser uma fonte de dados para mecanismos SQL
A versão inicial do SparkOnHBase foi criada para clientes da Cloudera que concordaram em permitir que o trabalho se tornasse público. Felizmente, recebi ajuda antecipada de colegas membros do Clouderans e do HBase PMC, Jon Hsieh e Matteo Bertozzi, e do membro do Spark PMC, Tathagata Das, para garantir que o design funcionasse tanto para o Apache Spark básico quanto para o Spark Streaming.
Não demorou muito para que outros clientes começassem a usar o SparkOnHBase, principalmente o Edmunds.com com seu aplicativo Spark Streaming em tempo real para o Super Bowl Sunday. Quando outras empresas aderiram, rapidamente ficou claro que um único mantenedor de projeto (ou seja:eu) não seria dimensionado. Felizmente, naquela época, a Cloudera havia anunciado recentemente o Cloudera Labs, que acabou sendo o lar perfeito para o projeto. Simplificando, o Cloudera Labs é um contêiner virtual para projetos de ecossistemas emergentes que são jovens em termos de prontidão, desenvolvimento e ambição empresarial, mas estão em alta demanda por usuários que desejam experimentar as tecnologias mais recentes. SparkOnHBase tornou-se um projeto Cloudera Labs no devido tempo.
Hoje, estou feliz em informar que SparkOnHBase foi recentemente comprometido com o tronco HBase (HBASE-13992). HBASE-13992 adiciona SparkOnHBase ao núcleo HBase sob um novo apelido, o módulo HBase-Spark. Quero agradecer ao vice-presidente da HBase, Andrew Purtell, por seu incentivo e “abrir a porta” para o HBASE-13992 e ao membro do PMC, Sean Busbey, por sua orientação e orientação. Além disso, quero agradecer a Elliott Clark, Enis Soztutar, Michael Stack, Nicolas Liochon, Kostas Sakellis, Ted Yu, Lars Hofhansl e Steve Loughran por suas revisões de código. (Como você pode ver, o SparkOnHBase foi um autêntico esforço da comunidade.)
Notavelmente, com o HBASE-13992, consegui adicionar código Spark e Scala ao projeto Apache HBase pela primeira vez. Foi superdivertido ter o privilégio de construir o primeiro teste unitário Scala na história do HBase!
Agora, vamos mergulhar nos detalhes técnicos.
Dentro do HBASE-13992
No HBASE-13992, você verá que a maior parte do código e design originais do SparkOnHBase permanecem inalterados. A arquitetura básica ainda se mantém, pois a parte central do código é projetada para obter um objeto de conexão HBase em cada Spark Executor.
Embora o básico permaneça, existem três grandes diferenças entre o patch HBASE-13992 e o projeto Cloudera Labs SparkOnHBase:
- APIs HBase: O HBASE-13992 usa todas as novas APIs do HBase 1.0+.
- Funções RDD e DStream: Uma das maiores reclamações sobre o SparkOnHBase estava relacionada à forma como as funções eram executadas; Os amantes do Spark queriam fazer ações do HBase diretamente de um RDD ou DStream. No HBASE-13992, esse recurso é incorporado por meio de testes de unidade e exemplos. Além disso, há exemplos de código de funções HBase diretamente de RDDs mais adiante neste post, para que você possa ter uma ideia de como as APIs serão.
- Fácil
foreach
emap
funções: Agora ficou ainda mais fácil fazerforeachPartition
semapPartition
s com uma conexão HBase. Um exemplo seguirá mais adiante nesta postagem.
Agora, vamos dar um rápido minuto e percorrer as diferenças entre a base de código SparkOnHBase e o patch HBASE-13992. Aqui está um exemplo rápido de
bulkDelete
do SparkOnHBase:val hbaseContext = new HBaseContext(sc, config); hbaseContext.bulkDelete[Array[Byte]](rdd, tableName, putRecord => new Delete(putRecord), 4);
Observe que neste exemplo estamos chamando uma função diretamente do objeto HBaseContext, mesmo que a operação estivesse realmente sendo executada no RDD. Então agora vamos olhar para o módulo HBase-Spark para o mesmo código:
val hbaseContext = new HBaseContext(sc, config) rdd.hbaseBulkDelete(hbaseContext, tableName, putRecord => new Delete(putRecord), 4)
A grande diferença é que o
hbaseBulkDelete
método vem direto do RDD. Além disso, essa abordagem deixa a porta aberta para as seguintes opções com um futuro JIRA:val hbaseContext = new HBaseContext(sc, config) rdd.hbaseBulkDelete(tableName)
Isso é o mais limpo possível por enquanto, mas o objetivo é torná-lo ainda mais simples e limpo.
Vamos também dar uma olhada rápida nas funções foreach e map no HBASE-13992. Você pode ver no
ForeachPartition
exemplo abaixo que temos um iterador e um HBase Connection
objeto. Isso nos dará poder total para fazer qualquer coisa com o HBase à medida que iteramos nossos valores:val hbaseContext = new HBaseContext(sc, config) rdd.hbaseForeachPartition(hbaseContext, (it, conn) => { val bufferedMutator = conn.getBufferedMutator(TableName.valueOf("t1")) ... bufferedMutator.flush() bufferedMutator.close() })
Finalmente, aqui está um exemplo de uma função de partição de mapa onde podemos obter um objeto de conexão à medida que iteramos nossos valores:
val getRdd = rdd.hbaseMapPartitions(hbaseContext, (it, conn) => { val table = conn.getTable(TableName.valueOf("t1")) var res = mutable.MutableList[String]() ... })
Trabalho futuro
Os seguintes JIRAs estão na minha lista de tarefas:
HBASE-14150 – Adicionar
BulkLoad
funcionalidade para o módulo HBase-Spark Em breve poderemos fazer cargas em massa diretamente de RDDs com código que parece tão simples quanto:
rdd.hbaseBulkLoad (tableName, t => { Seq((new KeyFamilyQualifier(t.rowKey, t.family, t.qualifier), t.value)). iterator }, stagingFolder)
HBASE-14181 – Adicionar Spark DataFrame DataSource ao módulo HBase-Spark
Com este patch, poderemos integrar diretamente o Spark SQL ao HBase e fazer coisas legais como pushdown de seleção de filtro e coluna, juntamente com pushdown de intervalo de varredura. O objetivo de obter a interação Spark SQL e HBase é tão simples quanto o seguinte:
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))
Existem outros JIRAs projetados para tornar o código mais fácil de usar e tornar o teste de unidade mais abrangente. Meu objetivo pessoal é poder relatar em uma postagem de blog de acompanhamento todo o grande progresso que estamos fazendo. O objetivo é transformar o Spark no cidadão de primeira classe que merece ser em relação ao HBase, solidificando-o ainda mais como o substituto do MapReduce na indústria. Substituir o MapReduce pelo Spark nos permitirá fazer ainda mais processamento em clusters HBase, sem adicionar a preocupação de que haverá mais contenção de E/S de disco.
Levará algum tempo até que o módulo HBase-Spark se torne uma versão do HBase. Enquanto isso, há planos de retroportar parte do código do módulo HBase-Spark para o SparkOnHBase no Cloudera Labs. Atualmente, o SparkOnHBase funciona no CDH 5.3 e 5.4, e o objetivo será atualizar o SparkOnHBase com os avanços do módulo HBase-Spark para a próxima versão secundária do CDH no final de 2015.
Ted Malaska é arquiteto de soluções na Cloudera, colaborador do Spark, Apache Flume e Apache HBase e coautor do livro O'Reilly, Arquiteturas de aplicativos Hadoop.