Dados e bancos de dados
O ecossistema Hadoop: HDFS, YARN, MapReduce, Hive, HBase e Spark
Intermediário11 min de leituraAtualizado
Esta página foi traduzida do inglês com a ajuda de IA e conferida com o original. Ler a versão em inglês
O Hadoop trouxe a ideia que moldou uma década de engenharia de dados: levar a computação até os dados e tolerar falhas por design. Este guia explica os blocos do HDFS e o NameNode, o agendamento no YARN, o MapReduce e os motivos pelos quais o Spark o desbancou, os papéis do Hive e do HBase, o modelo de DataFrame do Spark e o quanto dessa stack ainda faz sentido hoje.
O que você vai aprender
- Explicar como o HDFS divide, replica e localiza blocos e qual é o papel do NameNode
- Descrever como o YARN aloca contêineres e como as aplicações solicitam recursos
- Acompanhar um job MapReduce pelas fases de map, shuffle e reduce e explicar as vantagens do Spark
- Escolher entre Hive, HBase e Spark de acordo com o padrão de acesso aos dados
- Avaliar quais partes do ecossistema ainda vale a pena adotar e o que substituiu o restante
A contribuição do Hadoop não foi um software, mas uma postura: partir do princípio de que as máquinas são baratas e vão falhar, distribuir os dados entre elas e enviar a computação para onde os dados já estão. Isso inverteu a premissa da geração anterior, em que os dados eram levados até uma máquina grande e cara, e tornou possível analisar petabytes em hardware ao alcance de empresas comuns.
Duas décadas depois, a maior parte da implementação original foi superada e, ainda assim, o vocabulário — blocos, shuffles, partições, jobs, executors — continua sendo o vocabulário da engenharia de dados. Este guia mostra o que cada componente realmente faz, por que o Spark desbancou o MapReduce e quais peças ainda merecem lugar numa plataforma em 2026. As decisões de arquitetura ao redor — data lakes, formatos de tabela, streaming — são o tema do guia de arquitetura de big data.
HDFS: um sistema de arquivos feito para leituras sequenciais
O Hadoop Distributed File System divide cada arquivo em blocos de tamanho fixo, 128 MB por padrão, e armazena cada bloco em várias máquinas — três por padrão, em pelo menos dois racks. Essa única decisão de design explica a maior parte do seu comportamento.
Dois tipos de processo fazem o sistema funcionar:
- O NameNode mantém em memória toda a árvore de diretórios e o mapeamento entre blocos e DataNodes, e registra cada alteração em um edit log. Ele nunca lida diretamente com os dados dos arquivos: os clientes perguntam a ele onde um bloco está e depois conversam direto com os DataNodes.
- Os DataNodes armazenam os blocos como arquivos comuns em discos locais e se reportam por meio de heartbeats e relatórios de blocos. Quando um nó para de se reportar, o NameNode percebe que os blocos dele estão sub-replicados e manda outros nós copiá-los.
A memória do NameNode é o verdadeiro limite do sistema: cada arquivo, diretório e bloco precisa de um registro em memória de cerca de 150 bytes. Por isso, um milhão de arquivos pequenos custa muito mais do que um único arquivo grande com o mesmo tamanho total — o problema dos arquivos pequenos, que todo operador de Hadoop já enfrentou.
Três propriedades decorrem desse design e vale a pena deixá-las claras. O HDFS é write-once, append-only: não dá para atualizar no lugar, então os pipelines reescrevem partições inteiras. Ele prioriza throughput em vez de latência, o que faz dele um péssimo banco de dados e um excelente alvo para varreduras. E ele é rack-aware: posiciona as réplicas de modo que perder um rack inteiro não cause perda de dados e que os leitores possam preferir uma cópia local.
O Hadoop 3 trouxe duas mudanças importantes. A alta disponibilidade do NameNode roda um NameNode ativo e um standby que compartilham as alterações por meio de um quórum de JournalNodes, com o ZooKeeper cuidando do failover — antes disso, o NameNode era um genuíno ponto único de falha. E o erasure coding armazena paridade em vez de réplicas completas, reduzindo o overhead de armazenamento de 200% para cerca de 50% em dados frios, ao custo de mais CPU e de uma recuperação mais lenta.
hdfs dfs -put sales-2026-09.parquet /data/raw/sales/dt=2026-09-07/
hdfs dfs -ls -h /data/raw/sales/dt=2026-09-07/
hdfs fsck /data/raw/sales -files -blocks -locations
hdfs dfsadmin -report
YARN: agendando o cluster
O Yet Another Resource Negotiator separa o gerenciamento de recursos do cluster da lógica das aplicações que rodam nele, e foi isso que permitiu rodar num cluster Hadoop qualquer coisa além de MapReduce.
- O ResourceManager é o agendador de todo o cluster. Ele conhece a capacidade total e distribui contêineres, cada um uma reserva de memória e CPU em um nó específico.
- Um NodeManager roda em cada máquina, inicia os contêineres e informa a saúde e o consumo deles.
- Cada job submetido recebe primeiro um contêiner próprio para o seu ApplicationMaster. O ApplicationMaster então negocia mais contêineres para o trabalho de fato, monitora-os e reinicia o que falhar. Assim, o tratamento de falhas no nível do job fica na aplicação, não no agendador.
Na prática, dois agendadores importam. O Capacity Scheduler divide o cluster em filas hierárquicas com cotas garantidas e elasticidade opcional, o que se encaixa em organizações onde os departamentos têm capacidade contratada. O Fair Scheduler busca dar a cada aplicação em execução uma fatia igual ao longo do tempo, o que se encaixa em cargas ad hoc variadas. Em ambos os casos, a lição operacional recorrente é a mesma: um único job mal dimensionado pedindo contêineres enormes pode deixar todo o resto sem recursos, então limites de fila e tetos por usuário não são opcionais.
MapReduce, e por que o Spark o substituiu
O MapReduce expressa a computação como duas funções com uma ordenação entre elas.
- Map roda sobre cada split de entrada — geralmente um bloco do HDFS, agendado em um nó que o contém — e emite pares chave-valor.
- Shuffle e ordenação envia cada par ao reducer responsável pela sua chave, ordenando por chave no caminho. Essa é a parte cara: ela atravessa a rede e despeja dados em disco.
- Reduce recebe cada chave com todos os seus valores e emite o resultado.
A contagem de palavras é o exemplo canônico: o map emite (word, 1) para cada token e o reduce soma os valores por palavra. O modelo é de fato elegante, e o mesmo formato de map seguido de reduce aparece em código de aplicação comum — a Streams API do Java é a versão de uma única máquina da mesma ideia.
Suas fraquezas são estruturais, não cosméticas:
- Cada etapa é materializada em disco. Um pipeline de cinco transformações grava e relê o conjunto de dados inteiro cinco vezes, com replicação a cada gravação.
- Algoritmos iterativos são patológicos. Algoritmos de machine learning e de grafos percorrem os mesmos dados dezenas de vezes, pagando o custo total de I/O a cada passada.
- Apenas dois operadores. Joins, filtros, agregações e ordenações precisam ser montados à mão a partir de map e reduce, então os jobs reais viraram longas cadeias de classes Java.
- Somente batch. Nada de consultas interativas, nada de streaming.
O Apache Spark resolveu os quatro problemas com uma única mudança de modelo: manter o conjunto de dados em memória entre as etapas e descrever toda a computação como um grafo acíclico direcionado (DAG) de transformações antes de executar qualquer coisa. Com isso, o Spark consegue fundir transformações narrow em uma única passada, inserir um shuffle apenas onde os dados realmente precisam ser redistribuídos e reaproveitar dados em cache entre iterações. Os ganhos de velocidade divulgados — de dez a cem vezes em relação ao MapReduce — vinham principalmente da eliminação das gravações intermediárias, não de alguma aritmética engenhosa.
O modelo de programação do Spark
A abstração original do Spark era o RDD, um resilient distributed dataset: uma coleção imutável e particionada, com a linhagem registrada das operações que a produziram. É pela linhagem que ele se recupera — uma partição perdida é recalculada a partir das partições de origem, em vez de restaurada de uma réplica. As transformações (map, filter, join) são lazy; nada é executado até que uma ação (count, collect, write) force a avaliação.
O código Spark moderno deve usar DataFrames e Datasets. Eles carregam um schema, o que permite ao otimizador Catalyst reescrever a consulta — empurrando filtros até a varredura, descartando colunas não lidas, escolhendo estratégias de join — e ao engine Tungsten armazenar as linhas em memória off-heap compacta e gerar bytecode especializado. A consequência prática é que um pipeline com DataFrames costuma superar código RDD escrito à mão, do mesmo jeito que SQL declarativo supera um loop escrito à mão.
val orders = spark.read.parquet("s3a://lake/curated/orders")
val customers = spark.read.parquet("s3a://lake/curated/customers")
val topRegions = orders
.filter($"placed_at" >= "2026-01-01" && $"status" === "SHIPPED")
.join(customers.select($"id", $"region"), $"customer_id" === $"id")
.groupBy($"region")
.agg(sum($"total").as("revenue"), countDistinct($"customer_id").as("buyers"))
.orderBy($"revenue".desc)
topRegions.explain(true) // read the physical plan before trusting the job
topRegions.write.mode("overwrite").parquet("s3a://lake/serving/revenue_by_region")
O Spark SQL roda o mesmo engine sobre texto SQL, então analistas e engenheiros compartilham um único caminho de execução. O Structured Streaming reaproveita a API de DataFrame para entradas ilimitadas, com janelas por event time e estado persistido em checkpoints. O Spark 4 seguiu na mesma direção: a semântica ANSI SQL agora é o padrão, então overflow silencioso e truncamento implícito passam a ser erros; o Spark Connect desacopla o cliente do driver, permitindo que clientes leves enviem trabalho para um cluster remoto; e um tipo nativo VARIANT lida com dados semiestruturados sem explodir o schema.
Três conceitos de performance explicam a maior parte do tuning do Spark:
- Partições são a unidade de paralelismo. Poucas demais e os núcleos ficam ociosos; muitas demais e o overhead de agendamento domina. A adaptive query execution agora as combina automaticamente nas fronteiras de shuffle.
- Shuffles são a operação cara. Transformações wide (
groupBy,join,distinct) os provocam; as narrow, não. Um broadcast join evita o shuffle por completo quando um dos lados é pequeno o bastante para caber na memória de cada executor. - Skew — uma chave que concentra uma parcela desproporcional das linhas — deixa uma única task rodando muito depois de as outras terminarem. A adaptive execution consegue dividir partições desbalanceadas; aplicar salt à chave é o remédio manual.
Hive e HBase
O Apache Hive colocou SQL sobre arquivos. Uma consulta em HiveQL é compilada em um job — historicamente MapReduce, depois Tez e muitas vezes Spark — sobre dados no HDFS ou em object storage. Sua contribuição duradoura não é o engine de consultas, mas o Metastore: um banco relacional que registra quais tabelas existem, suas colunas e tipos, suas partições e a localização de seus arquivos. Esse catálogo sobreviveu ao próprio Hive; Spark, Trino, Flink e Impala o leem, e ele continua sendo um ponto comum de interoperabilidade mesmo em clusters sem nenhum Hadoop.
O Hive tem as características de um engine de varredura: throughput alto, latência na casa dos minutos para jobs grandes, nenhum índice digno do nome e um suporte a ACID adicionado a posteriori, que é melhor evitar em favor de um formato de tabela moderno. O LLAP adicionou daemons de longa duração e cache para tornar viáveis as consultas interativas, mas a maioria das equipes hoje aponta Trino ou Spark SQL para o mesmo metastore.
O Apache HBase é a ferramenta oposta: um banco wide-column inspirado no Bigtable, rodando sobre o HDFS, que oferece leituras e escritas aleatórias em milissegundos por chave de linha. Os dados são organizados em famílias de colunas, divididos em regiões por faixa de chave de linha e servidos por RegionServers; as escritas passam por um write-ahead log e por um store em memória que é descarregado em arquivos imutáveis, compactados em segundo plano.
Usar bem o HBase se resume inteiramente ao design da chave de linha. As chaves são armazenadas em ordem, então uma chave monotonicamente crescente (um timestamp, uma sequência) manda todas as escritas para uma única região — o problema de hotspotting, resolvido aplicando salt ou hash a um prefixo. Por outro lado, uma chave que começa pelo valor pelo qual você varre os dados torna eficientes as varreduras por faixa. Não há índices secundários, nem joins, nem planejador de consultas: ou você projeta a chave para o padrão de acesso, ou varre tudo. Para uma comparação com a abordagem de documentos diante do mesmo trade-off, veja o guia de MongoDB.
Ao redor deles ficam os outros nomes conhecidos: Sqoop para transferência em massa entre bancos relacionais e o HDFS, em grande parte substituído por change data capture para um broker, como descrito em arquitetura do Kafka; Oozie para orquestração de workflows, substituído pelo Airflow e agendadores semelhantes; Impala e Presto/Trino para SQL MPP interativo; ZooKeeper para coordenação, por baixo de vários dos anteriores; e o Apache Ozone, um object store mais recente projetado para resolver os limites do HDFS com arquivos pequenos e escala.
Onde o ecossistema está em 2026
O resumo honesto é que as ideias venceram e a maior parte da implementação foi substituída.
- O HDFS está em modo de manutenção na maioria das organizações. O object storage na nuvem oferece capacidade praticamente ilimitada, separa armazenamento de computação para que cada um escale de forma independente e custa menos. Spark e Trino o leem diretamente pelo conector S3A.
- O MapReduce é legado. Nada novo deve ser escrito sobre ele; os jobs existentes são migrados para o Spark.
- O YARN persiste on-premises, mas as novas implantações agendam o Spark no Kubernetes de forma esmagadora, o que unifica o modelo operacional com o resto da plataforma — contêineres, imagens e orquestração, como visto em fundamentos de Docker.
- O Hive como engine cedeu boa parte do espaço para Trino, Spark SQL e data warehouses na nuvem; o Metastore sobrevive, embora os catálogos REST do Iceberg o estejam substituindo aos poucos.
- O HBase permanece onde foi implantado, com Cassandra, ScyllaDB e key-value stores gerenciados na nuvem assumindo as cargas novas.
- O Spark vai muito bem, e é a peça do ecossistema que mais vale a pena aprender hoje.
Se você está herdando um cluster Hadoop, o caminho pragmático costuma ser: mover o armazenamento para object storage com um formato de tabela aberto, migrar os jobs MapReduce para o Spark, manter o metastore como catálogo até que um catálogo Iceberg o substitua e trocar o agendador do YARN pelo Kubernetes. Se você está começando do zero, quase certamente precisa de Spark e de um formato de tabela, e quase certamente não precisa de HDFS.
Principais pontos
- O HDFS armazena blocos grandes, replicados e imutáveis para maximizar o throughput sequencial; os metadados que o NameNode mantém em memória explicam por que arquivos pequenos causam tanto estrago.
- O YARN separa o gerenciamento de recursos da lógica das aplicações por meio do ResourceManager, dos NodeManagers e de um ApplicationMaster por job que solicita contêineres.
- O modelo map-shuffle-reduce do MapReduce é sólido, mas materializa cada etapa em disco, e foi isso que tornou a execução em memória baseada em DAG do Spark dez vezes mais rápida ou mais.
- Prefira DataFrames a RDDs no Spark para que o Catalyst e o Tungsten possam otimizar; faça o tuning observando partições, shuffles e skew.
- O Hive é uma camada SQL orientada a varreduras cujo Metastore sobreviveu a ele; o HBase é um banco wide-column de acesso aleatório em que o design da chave de linha determina tudo.
- Em 2026, fique com o Spark e com a ideia de catálogo, migre o armazenamento para object storage com um formato de tabela aberto e agende no Kubernetes em vez do YARN.
Fontes e leituras complementares
Perguntas frequentes
- O Hadoop morreu?
- O MapReduce, como modelo de programação, praticamente sim, e poucos projetos novos implantam HDFS. Mas as ideias do ecossistema e vários de seus componentes continuam vivos: o Hive Metastore ainda cataloga tabelas para engines que nunca tocam no Hadoop, o YARN ainda agenda clusters on-premises e o Spark, que cresceu dentro do ecossistema, nunca foi tão usado. Encare-o como infraestrutura para entender e herdar, não como base para construir algo novo.
- Por que o tamanho de bloco do HDFS é 128 MB?
- Porque um bloco grande dilui o custo de posicionamento no disco. Com blocos pequenos, um job passa a maior parte do tempo movendo as cabeças de leitura e perguntando ao NameNode onde estão os dados; com blocos grandes, ele lê em fluxo contínuo. Blocos grandes também mantêm a memória do NameNode sob controle, já que cada bloco exige um registro em memória. A contrapartida é que muitos arquivos pequenos desperdiçam tanto metadados de bloco quanto overhead de agendamento.
- Qual é a diferença entre Hive e HBase?
- Eles resolvem problemas opostos. O Hive é uma camada SQL sobre arquivos em massa para consultas analíticas de varredura completa, medidas em segundos ou minutos, sem nenhuma noção de atualização pontual. O HBase é um banco wide-column para leituras e escritas aleatórias em milissegundos por chave de linha, sem planejador de consultas e sem joins. Usar qualquer um deles para a carga de trabalho do outro só traz decepção.
- Devo rodar o Spark no YARN ou no Kubernetes?
- Kubernetes para qualquer coisa nova. Ele oferece o mesmo isolamento por contêineres que suas outras cargas de trabalho já usam, um único modelo operacional para toda a plataforma e escalabilidade elástica sobre instâncias na nuvem. O YARN continua sendo uma escolha razoável onde já existe um cluster Hadoop on-premises e o Capacity Scheduler dele codifica políticas multi-tenant reais que, de outra forma, você teria de reconstruir.