Introdução ao Apache Spark com exemplos e casos de uso
Publicados: 2022-03-11Ouvi falar do Spark pela primeira vez no final de 2013, quando me interessei pelo Scala, a linguagem em que o Spark é escrito. Algum tempo depois, fiz um projeto divertido de ciência de dados tentando prever a sobrevivência no Titanic. Essa acabou sendo uma ótima maneira de se aprofundar nos conceitos e na programação do Spark. Eu recomendo para qualquer aspirante a desenvolvedor Spark que esteja procurando um lugar para começar.
Hoje, o Spark está sendo adotado por grandes players como Amazon, eBay e Yahoo! Muitas organizações executam o Spark em clusters com milhares de nós. De acordo com o Spark FAQ, o maior cluster conhecido tem mais de 8.000 nós. De fato, o Spark é uma tecnologia que vale a pena observar e aprender.
Este artigo fornece uma introdução ao Spark, incluindo casos de uso e exemplos. Ele contém informações do site Apache Spark, bem como do livro Learning Spark - Lightning-Fast Big Data Analysis.
O que é Apache Spark? Uma introdução
Spark é um projeto Apache anunciado como “computação em cluster extremamente rápida”. Ele tem uma próspera comunidade de código aberto e é o projeto Apache mais ativo no momento.
O Spark fornece uma plataforma de processamento de dados mais rápida e geral. O Spark permite executar programas até 100x mais rápido na memória ou 10x mais rápido no disco do que o Hadoop. No ano passado, o Spark assumiu o Hadoop ao concluir o concurso Daytona GraySort de 100 TB 3x mais rápido em um décimo do número de máquinas e também se tornou o mecanismo de código aberto mais rápido para classificar um petabyte.
O Spark também possibilita escrever código mais rapidamente, pois você tem mais de 80 operadores de alto nível à sua disposição. Para demonstrar isso, vamos dar uma olhada no “Hello World!” de BigData: o exemplo do Word Count. Escrito em Java para MapReduce, ele tem cerca de 50 linhas de código, enquanto no Spark (e Scala) você pode fazer isso de maneira simples:
sparkContext.textFile("hdfs://...") .flatMap(line => line.split(" ")) .map(word => (word, 1)).reduceByKey(_ + _) .saveAsTextFile("hdfs://...")
Outro aspecto importante ao aprender a usar o Apache Spark é o shell interativo (REPL) que ele fornece pronto para uso. Usando REPL, pode-se testar o resultado de cada linha de código sem primeiro precisar codificar e executar todo o trabalho. O caminho para o código de trabalho é, portanto, muito mais curto e a análise de dados ad-hoc torna-se possível.
Os principais recursos adicionais do Spark incluem:
- Atualmente fornece APIs em Scala, Java e Python, com suporte para outras linguagens (como R) a caminho
- Integra-se bem com o ecossistema Hadoop e fontes de dados (HDFS, Amazon S3, Hive, HBase, Cassandra, etc.)
- Pode ser executado em clusters gerenciados pelo Hadoop YARN ou Apache Mesos e também pode ser executado de forma independente
O núcleo Spark é complementado por um conjunto de bibliotecas poderosas de nível superior que podem ser usadas perfeitamente no mesmo aplicativo. Atualmente, essas bibliotecas incluem SparkSQL, Spark Streaming, MLlib (para aprendizado de máquina) e GraphX, cada uma detalhada neste artigo. Bibliotecas e extensões adicionais do Spark também estão atualmente em desenvolvimento.
Núcleo Spark
O Spark Core é o mecanismo básico para processamento de dados paralelo e distribuído em larga escala. É responsável por:
- gerenciamento de memória e recuperação de falhas
- agendamento, distribuição e monitoramento de jobs em um cluster
- interagindo com sistemas de armazenamento
O Spark introduz o conceito de um RDD (Resilient Distributed Dataset), uma coleção de objetos distribuídos e tolerantes a falhas imutáveis que podem ser operados em paralelo. Um RDD pode conter qualquer tipo de objeto e é criado carregando um conjunto de dados externo ou distribuindo uma coleção do programa driver.
Os RDDs suportam dois tipos de operações:
- Transformações são operações (como map, filter, join, union e assim por diante) que são executadas em um RDD e que geram um novo RDD contendo o resultado.
- Ações são operações (como reduzir, contar, primeiro e assim por diante) que retornam um valor após executar um cálculo em um RDD.
As transformações no Spark são “preguiçosas”, o que significa que elas não computam seus resultados imediatamente. Em vez disso, eles apenas “lembram” a operação a ser executada e o conjunto de dados (por exemplo, arquivo) no qual a operação deve ser executada. As transformações só são realmente computadas quando uma ação é chamada e o resultado é retornado ao programa driver. Esse design permite que o Spark seja executado com mais eficiência. Por exemplo, se um arquivo grande fosse transformado de várias maneiras e passado para a primeira ação, o Spark processaria e retornaria apenas o resultado da primeira linha, em vez de fazer o trabalho para o arquivo inteiro.
Por padrão, cada RDD transformado pode ser recalculado toda vez que você executar uma ação nele. No entanto, você também pode persistir um RDD na memória usando o método persist ou cache; nesse caso, o Spark manterá os elementos no cluster para um acesso muito mais rápido na próxima vez que você o consultar.
SparkSQL
SparkSQL é um componente Spark que dá suporte à consulta de dados via SQL ou por meio da Hive Query Language. Ele se originou como a porta do Apache Hive para ser executado no Spark (no lugar do MapReduce) e agora está integrado à pilha do Spark. Além de fornecer suporte para diversas fontes de dados, possibilita tecer consultas SQL com transformações de código o que resulta em uma ferramenta muito poderosa. Abaixo está um exemplo de uma consulta compatível com Hive:
// sc is an existing SparkContext. val sqlContext = new org.apache.spark.sql.hive.HiveContext(sc) sqlContext.sql("CREATE TABLE IF NOT EXISTS src (key INT, value STRING)") sqlContext.sql("LOAD DATA LOCAL INPATH 'examples/src/main/resources/kv1.txt' INTO TABLE src") // Queries are expressed in HiveQL sqlContext.sql("FROM src SELECT key, value").collect().foreach(println)
Transmissão do Spark
O Spark Streaming suporta processamento em tempo real de dados de streaming, como arquivos de log do servidor web de produção (por exemplo, Apache Flume e HDFS/S3), mídias sociais como Twitter e várias filas de mensagens como Kafka. Sob o capô, o Spark Streaming recebe os fluxos de dados de entrada e divide os dados em lotes. Em seguida, eles são processados pelo mecanismo Spark e geram o fluxo final de resultados em lotes, conforme descrito abaixo.

A API Spark Streaming combina com a do Spark Core, tornando mais fácil para os programadores trabalharem nos mundos de dados em lote e streaming.
MLlib
MLlib é uma biblioteca de aprendizado de máquina que fornece vários algoritmos projetados para escalar horizontalmente em um cluster para classificação, regressão, agrupamento, filtragem colaborativa e assim por diante (confira o artigo da Toptal sobre aprendizado de máquina para obter mais informações sobre esse tópico). Alguns desses algoritmos também funcionam com dados de streaming, como regressão linear usando mínimos quadrados ordinários ou agrupamento k-means (e mais a caminho). O Apache Mahout (uma biblioteca de aprendizado de máquina para Hadoop) já se afastou do MapReduce e uniu forças no Spark MLlib.
GráficoX
GraphX é uma biblioteca para manipular gráficos e realizar operações paralelas a gráficos. Ele fornece uma ferramenta uniforme para ETL, análise exploratória e cálculos de gráficos iterativos. Além das operações integradas para manipulação de gráficos, ele fornece uma biblioteca de algoritmos gráficos comuns, como o PageRank.
Como usar o Apache Spark: caso de uso de detecção de eventos
Agora que respondemos à pergunta “O que é o Apache Spark?”, vamos pensar em quais tipos de problemas ou desafios ele pode ser usado de maneira mais eficaz.
Me deparei com um artigo recentemente sobre um experimento para detectar um terremoto analisando um fluxo do Twitter. Curiosamente, foi demonstrado que essa técnica provavelmente informava sobre um terremoto no Japão mais rápido do que a Agência Meteorológica do Japão. Mesmo que eles tenham usado uma tecnologia diferente em seu artigo, acho que é um ótimo exemplo para ver como poderíamos usar o Spark com trechos de código simplificados e sem o código de cola.
Primeiro, teríamos que filtrar os tweets que parecem relevantes como “terremoto” ou “tremor”. Poderíamos facilmente usar o Spark Streaming para esse fim da seguinte forma:
TwitterUtils.createStream(...) .filter(_.getText.contains("earthquake") || _.getText.contains("shaking"))
Então, teríamos que fazer uma análise semântica nos tweets para determinar se eles parecem estar referenciando uma ocorrência atual de terremoto. Tweets como "Terremoto!" ou "Agora está tremendo", por exemplo, seriam considerados correspondências positivas, enquanto tweets como "Participar de uma conferência sobre terremoto" ou "O terremoto de ontem foi assustador" não. Os autores do artigo utilizaram uma máquina de vetores de suporte (SVM) para esta finalidade. Faremos o mesmo aqui, mas também podemos tentar uma versão de streaming. Um exemplo de código resultante do MLlib seria semelhante ao seguinte:
// We would prepare some earthquake tweet data and load it in LIBSVM format. val data = MLUtils.loadLibSVMFile(sc, "sample_earthquate_tweets.txt") // Split data into training (60%) and test (40%). val splits = data.randomSplit(Array(0.6, 0.4), seed = 11L) val training = splits(0).cache() val test = splits(1) // Run training algorithm to build the model val numIterations = 100 val model = SVMWithSGD.train(training, numIterations) // Clear the default threshold. model.clearThreshold() // Compute raw scores on the test set. val scoreAndLabels = test.map { point => val score = model.predict(point.features) (score, point.label) } // Get evaluation metrics. val metrics = new BinaryClassificationMetrics(scoreAndLabels) val auROC = metrics.areaUnderROC() println("Area under ROC = " + auROC)
Se estivermos satisfeitos com a taxa de previsão do modelo, podemos passar para o próximo estágio e reagir sempre que descobrirmos um terremoto. Para detectar um, precisamos de um certo número (ou seja, densidade) de tweets positivos em uma janela de tempo definida (conforme descrito no artigo). Observe que, para tweets com serviços de localização do Twitter ativados, também extraímos a localização do terremoto. De posse desse conhecimento, poderíamos usar o SparkSQL e consultar uma tabela Hive existente (armazenando usuários interessados em receber notificações de terremotos) para recuperar seus endereços de e-mail e enviar a eles um e-mail de aviso personalizado, como segue:
// sc is an existing SparkContext. val sqlContext = new org.apache.spark.sql.hive.HiveContext(sc) // sendEmail is a custom function sqlContext.sql("FROM earthquake_warning_users SELECT firstName, lastName, city, email") .collect().foreach(sendEmail)
Outros casos de uso do Apache Spark
Casos de uso em potencial para o Spark vão muito além da detecção de terremotos, é claro.
Aqui está uma amostra rápida (mas certamente nem de longe exaustiva!) de outros casos de uso que exigem lidar com a velocidade, variedade e volume de Big Data, para os quais o Spark é tão adequado:
Na indústria de jogos, processar e descobrir padrões do potencial de eventos em tempo real no jogo e ser capaz de responder a eles imediatamente é uma capacidade que pode render um negócio lucrativo, para fins como retenção de jogadores, publicidade direcionada, -ajuste do nível de complexidade, e assim por diante.
No setor de comércio eletrônico, as informações de transação em tempo real podem ser passadas para um algoritmo de cluster de streaming como k-means ou filtragem colaborativa como ALS. Os resultados podem até ser combinados com outras fontes de dados não estruturadas, como comentários de clientes ou análises de produtos, e usados para melhorar e adaptar constantemente as recomendações ao longo do tempo com novas tendências.
No setor financeiro ou de segurança, a pilha Spark pode ser aplicada a um sistema de detecção de fraude ou intrusão ou autenticação baseada em risco. Ele poderia obter resultados de alto nível coletando grandes quantidades de logs arquivados, combinando-os com fontes de dados externas, como informações sobre violações de dados e contas comprometidas (consulte, por exemplo, https://haveibeenpwned.com/) e informações da conexão/ solicitação, como geolocalização de IP ou hora.
Conclusão
Para resumir, o Spark ajuda a simplificar a tarefa desafiadora e computacionalmente intensiva de processar grandes volumes de dados em tempo real ou arquivados, estruturados e não estruturados, integrando perfeitamente recursos complexos relevantes, como aprendizado de máquina e algoritmos de gráficos. O Spark traz o processamento de Big Data para as massas. Confira!