O Spark é uma promissora solução de analítica de Big Data desenvolvida para a computação em cluster altamente eficiente usando o processamento na memória. Seus modelos de uso direcionados incluem os que incorporam algoritmos iterativos (ou seja, os que podem se beneficiar da manutenção de dados na memória em vez do envio a um sistema de arquivos com latência mais alta). Antes de fazer esses exercícios, certifique-se de entender totalmente a abordagem do Spark para a computação em cluster e suas diferenças em relação ao Hadoop. Leia sobre o contexto e uso do Spark no recente artigo complementar Spark, uma alternativa para a analítica de dados rápida.
Esses exercícios oferecerão prática nas seguintes áreas:
- Instalar e fazer experiências com a linguagem Scala
- Conhecer as coleções do Scala
- Instalar o Spark e executar a sua primeira tarefa
- Melhorar o desempenho por meio do multiencadeamento
- Melhorar o desempenho por meio da configuração
Este conjunto de exercícios requer um conhecimento básico de Linux®, como a capacidade de instalar novos aplicativos. O conhecimento da linguagem Scala é benéfico, mas não obrigatório. Os exercícios devem ser feitos na ordem, já que ilustram a instalação dos pacotes de software necessários.
Exercício 1: instalar e fazer experiências com a linguagem Scala
Comece instalando a linguagem Scala. O processo de instalação do Scala varia de acordo com a plataforma. No pior dos casos, pode-se fazer o download da árvore de origem e executar uma criação e instalação. Já que o Spark requer uma versão do Scala mais recente do que a oferecida por meio dos gerenciadores de pacote, instale a partir da árvore de origem.
Depois de instalar, inicie o interpretador do Scala (demonstrado no artigo complementar "Spark, uma alternativa para a analítica de dados rápida", em Recursos), experimente alguns dos exemplos (das Listagens 1 a 3) e verifique os resultados.
Exercício 2: conheça as coleções do Scala
A biblioteca de coleções é um recurso interessante do Scala. Uma coleção no Scala é um contêiner com zero ou mais coisas, como uma lista, um conjunto ou mapa. Esse conceito é relevante para o Spark, já que é possível operar nos seus conjuntos de dados distribuídos como se fosse uma coleção local. Pode-se aprender mais sobre as coleções de Scala na API Scala 2.8 Collections . Consulte essa referência para ver como criar um array e uma coleção de listas.
Execute as etapas a seguir:
- Crie um array de
ints e aplique o métodoreversepara inverter o conteúdo. - Crie uma lista de sequências e itere-as para imprimi-las individualmente.
Exercício 3: instale o Spark e execute a sua primeira tarefa
Faça o download da versão mais recente do Spark. A forma mais fácil de obtê-lo é por meio do git:
$ git clone git://github.com/mesos/spark.git |
O resultado dessa linha de comando é um novo subdiretório chamado ./spark.
Execute cd para esse subdiretório. Agora atualize e compile a distribuição com a ferramenta de criação simples (sbt):
$ sbt/sbt update compile |
O resultado dessa ação é o download de vários pacotes e a compilação de várias origens do Scala. Para concluir a configuração, acesse o subdiretório ./spark/conf, renomeie spark-env.sh-template como spark-env.sh e inclua a linha a seguir:
export SCALA_HOME=/opt/scala-2.9.1.final |
Lembre-se também de incluir SCALA_HOME/bin no PATH.
Agora que o Spark está instalado, execute o programa de exemplo SparkPi com um encadeamento no host local. Use o artigo complementar como guia para realizar essa tarefa. (Consulte o artigo "Spark, uma alternativa para a analítica de dados rápida" em Recursos).)
Exercício 4: melhore o desempenho com o multiencadeamento
Este exercício explora a diferença do multiencadeamento e do Spark. Usando o programa de amostra SparkPi, é possível alterar o número de encadeamentos associados a uma execução específica.
Usando o artigo de referência como guia, faça experiências com o parâmetro threads
no contexto local e observe a diferença nos tempos de execução.
Exercício 5: melhore o desempenho por meio da configuração
O Spark suporta vários elementos de configuração que possibilitam um desempenho melhor. Considerando uma configuração de cluster do Spark com o Mesos:
- Quais itens de configuração (consulte ./conf) podem ajudar no desempenho, considerando o recurso de processamento na memória do Spark?
- Da mesma forma (consulte o link das FAQ do Spark em Recursos), qual propriedade de sistema pode melhorar o desempenho do armazenamento em cache de conjuntos de dados?
Algumas saídas podem variar de acordo com a versão do Scala e do Spark.
Instale o Scala e experimente alguns exemplos (ilustrados na Listagem 1). No artigo complementar — "Spark, uma alternativa para a analítica de dados rápida" — em Recursos), pode-se ver como o Scala é instalado a partir de sua distribuição e colocado à disposição. É possível incluir as exportações no seu ambiente para torná-las persistentes.
Listagem 1. Instalando e fazendo experiências com o Scala
$ wget http://www.scala-lang.org/downloads/distrib/files/scala-2.9.1.final.tgz $ sudo tar xvfz scala-2.9.1.final.tgz --directory /opt $ export SCALA_HOME=/opt/scala-2.9.1.final $ export PATH=$SCALA_HOME/bin:$PATH $ echo $PATH /opt/scala-2.9.1.final/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin $ $ scala Welcome to Scala version 2.9.1.final (OpenJDK Client VM, Java 1.6.0_20). Type in expressions to have them evaluated. Type :help for more information. scala> def square(x: Int) = x*x square: (x: Int)Int scala> square(3) res0: Int = 9 scala> square(res0) res1: Int = 81 scala> :quit $ |
Para esses exemplos, use o interpretador do Scala para verificar os seus resultados. A Listagem 2 dá a solução do exercício de array.
Listagem 2. Criando e invertendo um array
scala> val numbers = Array(1, 2, 3, 4, 5, 6, 7, 8, 9) numbers: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9) scala> numbers.reverse res1: Array[Int] = Array(9, 8, 7, 6, 5, 4, 3, 2, 1) scala> |
A Listagem 3 dá a solução do exercício de lista.
Listagem 3. Criando e iterando uma lista de sequências
scala> val animals = List("dog", "cat", "mouse")
animals: List[java.lang.String] = List(dog, cat, mouse)
scala> animals foreach println
dog
cat
mouse
scala> for (elem <- animals) println(elem)
dog
cat
mouse
scala> |
Você executa o teste do SparkPi por meio do comando ./run
, especificando o aplicativo e o host/fatias. Essa tarefa é realizada na Listagem 4.
Listagem 4. Executando o teste do SparkPi localmente
$ ./run spark.examples.SparkPi local 12/01/23 20:55:33 INFO spark.CacheTrackerActor: Registered actor on port 7077 12/01/23 20:55:33 INFO spark.MapOutputTrackerActor: Registered actor on port 7077 12/01/23 20:55:33 INFO spark.SparkContext: Starting job... 12/01/23 20:55:33 INFO spark.CacheTracker: Registering RDD ID 0 with cache 12/01/23 20:55:33 INFO spark.CacheTrackerActor: Registering RDD 0 with 2 partitions 12/01/23 20:55:33 INFO spark.CacheTrackerActor: Asked for current cache locations 12/01/23 20:55:33 INFO spark.LocalScheduler: Final stage: Stage 0 12/01/23 20:55:33 INFO spark.LocalScheduler: Parents of final stage: List() 12/01/23 20:55:33 INFO spark.LocalScheduler: Missing parents: List() 12/01/23 20:55:33 INFO spark.LocalScheduler: Submitting Stage 0, has no missing parents 12/01/23 20:55:33 INFO spark.LocalScheduler: Running task 0 12/01/23 20:55:33 INFO spark.LocalScheduler: Size of task 0 is 1481 bytes 12/01/23 20:55:34 INFO spark.LocalScheduler: Finished task 0 12/01/23 20:55:34 INFO spark.LocalScheduler: Running task 1 12/01/23 20:55:34 INFO spark.LocalScheduler: Completed ResultTask(0, 0) 12/01/23 20:55:34 INFO spark.LocalScheduler: Size of task 1 is 1481 bytes 12/01/23 20:55:34 INFO spark.LocalScheduler: Finished task 1 12/01/23 20:55:34 INFO spark.LocalScheduler: Completed ResultTask(0, 1) 12/01/23 20:55:34 INFO spark.SparkContext: Job finished in 0.3042134 s Pi is roughly 3.13768 $ |
A execução do programa de teste do SparkPi com números diferentes de encadeamento é especificada facilmente com o argumento local (host). O número especificado é o número de encadeamentos a serem associados à execução. Evidentemente, a forma de execução disso varia de acordo com o número de encadeamentos de hardware no seu sistema. A solução na Listagem 5 ilustra a execução de um e dois encadeamentos.
Como mostrado, a primeira execução com um encadeamento requer 0,59 segundos, ao passo que a segunda, com dois encadeamentos, conclui em 0,9 segundos. A velocidade pode variar.
Listagem 5. Executando o SparkPi com um número diferente de encadeamentos
$ ./run spark.examples.SparkPi local[1] 12/01/24 18:50:41 INFO spark.CacheTrackerActor: Registered actor on port 7077 12/01/24 18:50:41 INFO spark.MapOutputTrackerActor: Registered actor on port 7077 12/01/24 18:50:41 INFO spark.SparkContext: Starting job... 12/01/24 18:50:41 INFO spark.CacheTracker: Registering RDD ID 0 with cache 12/01/24 18:50:41 INFO spark.CacheTrackerActor: Registering RDD 0 with 2 partitions 12/01/24 18:50:41 INFO spark.CacheTrackerActor: Asked for current cache locations 12/01/24 18:50:41 INFO spark.LocalScheduler: Final stage: Stage 0 12/01/24 18:50:41 INFO spark.LocalScheduler: Parents of final stage: List() 12/01/24 18:50:41 INFO spark.LocalScheduler: Missing parents: List() 12/01/24 18:50:41 INFO spark.LocalScheduler: Submitting Stage 0, has no missing parents 12/01/24 18:50:41 INFO spark.LocalScheduler: Running task 0 12/01/24 18:50:41 INFO spark.LocalScheduler: Size of task 0 is 1481 bytes 12/01/24 18:50:42 INFO spark.LocalScheduler: Finished task 0 12/01/24 18:50:42 INFO spark.LocalScheduler: Running task 1 12/01/24 18:50:42 INFO spark.LocalScheduler: Size of task 1 is 1481 bytes 12/01/24 18:50:42 INFO spark.LocalScheduler: Completed ResultTask(0, 0) 12/01/24 18:50:42 INFO spark.LocalScheduler: Finished task 1 12/01/24 18:50:42 INFO spark.LocalScheduler: Completed ResultTask(0, 1) 12/01/24 18:50:42 INFO spark.SparkContext: Job finished in 0.595091783 s Pi is roughly 3.12736 $ ./run spark.examples.SparkPi local[2] 12/01/24 18:50:46 INFO spark.MapOutputTrackerActor: Registered actor on port 7077 12/01/24 18:50:46 INFO spark.CacheTrackerActor: Registered actor on port 7077 12/01/24 18:50:46 INFO spark.SparkContext: Starting job... 12/01/24 18:50:46 INFO spark.CacheTracker: Registering RDD ID 0 with cache 12/01/24 18:50:46 INFO spark.CacheTrackerActor: Registering RDD 0 with 2 partitions 12/01/24 18:50:46 INFO spark.CacheTrackerActor: Asked for current cache locations 12/01/24 18:50:46 INFO spark.LocalScheduler: Final stage: Stage 0 12/01/24 18:50:46 INFO spark.LocalScheduler: Parents of final stage: List() 12/01/24 18:50:46 INFO spark.LocalScheduler: Missing parents: List() 12/01/24 18:50:46 INFO spark.LocalScheduler: Submitting Stage 0, has no missing parents 12/01/24 18:50:46 INFO spark.LocalScheduler: Running task 0 12/01/24 18:50:46 INFO spark.LocalScheduler: Running task 1 12/01/24 18:50:46 INFO spark.LocalScheduler: Size of task 0 is 1481 bytes 12/01/24 18:50:46 INFO spark.LocalScheduler: Size of task 1 is 1481 bytes 12/01/24 18:50:46 INFO spark.LocalScheduler: Finished task 1 12/01/24 18:50:46 INFO spark.LocalScheduler: Finished task 0 12/01/24 18:50:46 INFO spark.LocalScheduler: Completed ResultTask(0, 0) 12/01/24 18:50:46 INFO spark.LocalScheduler: Completed ResultTask(0, 1) 12/01/24 18:50:46 INFO spark.SparkContext: Job finished in 0.098092002 s Pi is roughly 3.14388 $ |
Observe que, em vez de local, é possível fornecer um mestre de Mesos para se conectar, que suporta um cluster de nós em vez de vários encadeamentos em um único nó (a opção com melhor desempenho).
Para ver quantos encadeamentos de hardware (CPUs virtuais) estão disponíveis para você, execute a seguinte linha de comando:
$ grep processor /proc/cpuinfo |
Embora o arquivo de configuração do Spark (./conf/spark-env.sh) defina os elementos-chave do ambiente, uma opção (SPARK_MEM)
especifica a quantidade de memória que deve ser suportada para a Java™ Virtual Machine de cada nó. Devido ao foco do Spark nos conjuntos de dados na memória, uma quantidade maior de memória terá como resultado um desempenho melhor (dependente da carga de trabalho).
Conforme o definido nas FAQ do Spark, alguns conjuntos de dados podem não caber inteiramente na memória. Quando isso acontece, o Spark volta a computar a partição que não coube (o valor padrão) ou, se estiver configurado para isso, armazenar a partição em cache no disco. Para passar a partição para o disco em vez de computá-la novamente, use a propriedade spark.DiskSpillingCache .
Aprender
- Saiba mais sobre a linguagem de programação Scala no website do projeto.
- Saiba mais sobre Spark Cluster Computing Frameworks no website do projeto.
- Leia o artigo do autor — Spark, uma alternativa para a analítica de dados rápida — sobre o contexto e uso do Spark. (developerWorks, novembro de 2011).
- Examine a API Scala 2.8 Collections para obter informações sobre as coleções do Scala e ver como criar um array e uma coleção de listas. (Martin Odersky e Lex Spoon, setembro de 2010).
- Visite a FAQ do Spark para obter mais informações.
- Na rotina zona Linux do developerWorks, encontre vários artigos de instruções e tutoriais, bem como downloads, fóruns de discussão e muitos outros recursos para desenvolvedores e administradores Linux.
- Visite o
zona de software livre do developerWorks para ter acesso a uma grande quantidade de informações sobre ferramentas de software livre e o uso de tecnologias livres.
- Fique por dentro dos eventos técnicos e webcasts do developerWorks com foco em uma variedade de produtos IBM e tópicos do segmento de mercado de TI.
- Participe de um briefing ao vivo e gratuito do developerWorks para se atualizar rapidamente sobre produtos e ferramentas IBM, bem como tendências do segmento de mercado de TI.
- Acompanhe as demos on demand do developerWorks , que abrangem desde demos de instalação e configuração de produtos para iniciantes até funcionalidades avançadas para desenvolvedores experientes.
- Siga o Tim no Twitter. Também é possível seguir DeveloperWorks no Twitter, ou inscreva-se em um feed de tweets sobre o Linux no developerWorks.
Obter produtos e tecnologias
- Instale a versão mais recente do Scala a partir da árvore de origem
- Avalie produtos IBM da maneira que for melhor para você: faça download da versão de teste de um produto, avalie um produto on-line, use-o em um ambiente de nuvem ou passe algumas horas na SOA Sandbox aprendendo a implementar Arquitetura Orientada a Serviços de modo eficiente.
Discutir
- Participe da comunidade do developerWorks. Entre em contato com outros usuários do developerWorks e explore os blogs, fóruns, grupos e wikis voltados para desenvolvedores.

M. Tim Jones é arquiteto de firmware integrado e autor de Artificial Intelligence: A Systems Approach, GNU/Linux Application Programming (agora em sua segunda edição), AI Application Programming (em sua segunda edição) e BSD Sockets Programming from a Multilanguage Perspective. Seu conhecimento em engenharia varia do desenvolvimento de kernels para naves espaciais geossíncronas até a arquitetura de sistemas embarcados e o desenvolvimento de protocolos de rede. Tim é arquiteto de plataforma da Intel e autor em Longmont, Colorado.