Apache Spark
Plataforma de Computação Distribuída

Com a evolução das redes de computadores, um novo paradigma computacional surgiu e se tornou extremamente poderoso: a possibilidade de distribuição do processamento entre computadores diferentes.
A computação distribuída permite a repartição e especialização das tarefas computacionais, segundo a natureza e função de cada computador.
Esse paradigma surgiu para solucionar um grande problema da computação, que é a necessidade de computadores com poder de processamento suficiente para realizar a análise do grande volume de dados disponível atualmente.

Características do Apache Spark
O Apache Spark é um mecanismo de análise unificada para processamento de dados em larga escala em computação distribuída.
Criado em 2009 na Universidade da Califórnia pelo AMPLab de Berkeley, o Spark rapidamente ganhou uma grande comunidade, levando à sua adoção pela Apache Software Foundation em 2013.
Desenvolvedores de mais de 300 empresas auxiliaram na sua implementação, e uma vasta comunidade com mais de 1.200 desenvolvedores de centenas de organizações continuam a contribuir para seu contínuo refinamento.
É usado por organizações em uma gama de setores e sua comunidade de desenvolvedores é uma das maiores existentes.
O poder do Spark vem do seu processamento em memória (in-memory).
Ele usa um conjunto distribuído de nós com muita memória e codifica ção de dados compacta, juntamente com um planejador de consultas (query planner) otimizado para minimizar o tempo de execução e a demanda por memória.
Como realiza cálculos em memória (in-memory), pode processar até 100 vezes mais rápido do que as estruturas que processam no disco.
É ideal para processar grandes volumes de dados em Analytics, treinamento de modelos para aprendizado de máquina e IA.
Adicionalmente, o Spark executa uma pilha de bibliotecas nativas de aprendizado de máquina e processamento de gráficos e estruturas de dados semelhantes a SQL, permitindo um desempenho excepcional.
Conta com mais de 80 operadores de alto nível, facilitando a criação de aplicativos paralelos.
O Spark guarda algumas semelhanças com o Hadoop. Ambos são estruturas de código aberto para processamento de dados analíticos, vivem na Apache Software Foundation, contêm bibliotecas de aprendizado de máquina e podem ser programados em várias linguagens diferentes.
No entanto, o Spark estende o número de cálculos possíveis com o Hadoop, aprimorando o componente de processamento de dados nativo do Hadoop, o MapReduce.
O Spark usa a infraestrutura do Hadoop Distributed File System (HDFS), mas melhora suas funcionalidades e fornece ferramentas adicionais, como a implementação de aplicativos em um cluster Hadoop (com SIMR - Spark Inside MapReduce) ou YARN.

Arquitetura do Apache Spark
O Apache Spark é um mecanismo de processamento distribuído que opera no princípio de coordenador/trabalhador.
Sua arquitetura consiste nos seguintes componentes principais:
-
Spark Driver: É o mestre da arquitetura Spark. É a aplicação principal que gerencia a criação e execução do processamento definido pelo programador.
-
Cluster Manager: Um componente opcional necessário apenas se o Spark for executado de forma distribuída. Ele é responsável por gerenciar as máquinas que serão usadas como trabalhadores (workers).
-
Spark Workers: São as máquinas que executam efetivamente as tarefas enviadas pelo programa Driver. Se o Spark for executado de forma local, a máquina pode desempenhar tanto o papel de Driver quanto de Worker.

Componentes Fundamentais do Modelo de Programação Spark
-
Resilient Distributed Datasets (RDD): O principal objeto do modelo de programação Spark. É nesses objetos que os dados são processados. Eles armazenam os dados na memória para realizar várias operações como carregamento, transformação e ações (cálculos, gravações, filtros, uniões e map-reduce) nos dados. Abstraem um conjunto de objetos distribuídos no cluster, geralmente executados na memória principal. Podem estar armazenados em sistemas de arquivo tradicional, no HDFS e em alguns bancos de dados NoSQL, como o HBase.
-
Operações: Representam transformações (agrupamentos, filtros, mapeamento de dados) ou ações (contagens e persistências) realizadas em um RDD. Um programa Spark normalmente é definido como uma sequência de transformações ou ações realizadas em um conjunto de dados.
-
Spark Context: O contexto é o objeto que conecta o Spark ao programa que está sendo desenvolvido. Pode ser acessado como uma variável em um programa.
Bibliotecas do Apache Spark
Além das APIs, existem bibliotecas que compõem seu ecossistema e fornecem capacidades adicionais:
-
Spark Streaming: Pode ser usado para processar dados de streaming em tempo real com base na computação de microbatch. Para isso, utiliza o DStream, que é basicamente uma série de RDDs para processar os dados em tempo real. É escalável, possui alto throughput, tolerante a falhas e suporta workloads batch ou streaming. O Spark Streaming permite a leitura/gravação a partir/para tópicos Kafka nos formatos texto, csv, avro e json.
-
Spark SQL: Fornece a capacidade de expor os conjuntos de dados Spark por meio de uma API JDBC. Isso permite a execução de consultas no estilo SQL sobre esses dados, fazendo uso de ferramentas tradicionais de BI e visualização. Além disso, permite a utilização de ETL para extração de dados em diferentes formatos (Json, Parquet ou Banco de dados), transformá-los e expô-los para consultas ad-hoc.
-
Spark MLlib: A biblioteca de aprendizagem de máquina do Spark, que consiste em algoritmos de aprendizagem, incluindo classificação, regressão, clustering, filtragem colaborativa e redução de dimensionalidade.
-
Spark GraphX: Uma nova API do Spark para grafos e computação paralela. Simplificando, estende os RDDs do Spark para grafos. Para apoiar a computação de grafos, expõe um conjunto de operadores fundamentais (subgrafos e vértices adjacentes), bem como uma variante otimizada do Pregel. Além disso, inclui uma crescente coleção de algoritmos para simplificar tarefas de análise de grafos.
-
Variáveis Compartilhadas: O Spark oferece dois tipos de variáveis compartilhadas para torná-lo mais eficiente na execução em clusters:
-
Broadcast: São variáveis somente leitura (read-only) que são armazenadas em cache em todos os nós do cluster para acesso ou uso por tarefas. Em vez de enviar os dados junto com cada tarefa, o Spark distribui as variáveis de transmissão (broadcast) na máquina usando algoritmos eficientes de transmissão para reduzir os custos de comunicação.
-
Accumulator (Acumuladoras): São variáveis compartilhadas apenas adicionadas por meio de uma operação associativa e comutativa, usadas para executar contadores (similar aos contadores MapReduce) ou operações de soma.
-
Fluxo de Trabalho do Apache Spark
Seu ciclo de vida envolve vários passos intermediários, cada um responsável por conduzir responsabilidades específicas.
- O processo se inicia com a submissão do job pelo cliente, por meio da opção spark-submit.
- A classe main, especificada durante a submissão do job, é chamada e o programa Spark driver é iniciado no nó master, responsável por gerenciar o ciclo de vida do aplicativo.
- O programa driver solicita recursos do cluster manager para iniciar os executores com base na configuração do aplicativo.
- O cluster manager ativa o executor no nó worker em nome do driver Spark, que agora assume a propriedade do ciclo de vida do aplicativo.
- O driver Spark cria uma DAG com base no RDD. A tarefa é então dividida em etapas. O driver Spark envia as tarefas para o executor, que as executa.
- O executor envia uma solicitação de conclusão da tarefa ao driver por meio do cluster manager. Depois que todas as tarefas são concluídas em todos os executores, o driver envia um status de conclusão ao cluster manager.

Outras Características do Apache Spark
- O Spark pode acessar fontes de dados variáveis e executar em várias plataformas, incluindo o Hadoop.
- Fornece APIs funcionais de alto nível em Java, Scala, Python e R para:
- manipulação de dados em grande escala
- armazenamento em cache de dados in-memory
- reutilização de datasets
- Suporta vários formatos e conjuntos de APIs para lidar com qualquer tipo de dado em modo distribuído.
- Oferece um mecanismo otimizado com suporte a gráficos de execução geral.
- Utiliza o conceito de grafo acíclico direcionado (DAG), por meio do qual é possível desenvolver pipelines compostos por várias etapas complexas.
- A capacidade de armazenamento de dados in-memory e processamento near real-time torna o Spark mais rápido que o framework MapReduce e oferece uma vantagem para casos de uso iterativos onde o mesmo dataset é usado várias vezes em diferentes execuções.
Boas Práticas para Apache Spark
-
Uso de Dataframe/Dataset sobre RDD: O RDD serializa e desserializa sempre que distribui os dados entre clusters. Essas operações são muito caras. Por outro lado, o Dataframe armazena os dados como binários, usando armazenamento off-heap, sem a necessidade de serialização e desserialização de dados na distribuição para clusters, tornando-se uma grande vantagem em relação ao RDD.
-
Uso do Coalesce para Reduzir o Número de Partições: Sempre que for necessário reduzir o número de partições, use o coalesce, pois ele faz o movimento mínimo de dados sobre a partição. Por outro lado, o repartition recria toda a partição, tornando a movimentação de dados muito alta. Para aumentar o número de partições, temos que usar o repartition.
-
Uso de Formatos de Dados Serializados: Geralmente, seja um job de streaming ou em lote, o Spark grava os resultados calculados em algum arquivo de saída, e outro job do Spark o consome, faz alguns cálculos e grava novamente em algum arquivo de saída. Nesse cenário, usar um formato de arquivo serializado, como Parquet, nos dá uma vantagem significativa sobre os formatos CSV e JSON.
-
Evitando Funções Definidas pelo Usuário: Use as funções pré-construídas do Spark sempre que possível. As funções UDF (User Defined Functions) são uma caixa preta para o Spark, impedindo-o de aplicar otimizações. Dessa forma, perdemos todos os recursos de otimização oferecidos pelo Dataframe/Dataset do Spark.
-
Dados de Memória em Cache: Sempre que fazemos uma sequência de transformações do Dataframe e precisamos usar um Dataframe intermediário repetidamente para cálculos adicionais, o Spark fornece um recurso para armazenar um DF específico na memória na forma de um cache.
Detalhes do Projeto Apache Spark
O Spark é escrito na linguagem Scala e executado em uma máquina virtual Java. Atualmente, suporta as seguintes linguagens para desenvolvimento de aplicativos:
- Scala
- Java
- Python
- Clojure
- R
