Hadoop i l'Ecosistema Big Data
Introducció
Apache Hadoop va néixer d'una necessitat real: Google havia publicat el 2003 el paper del Google File System (GFS) i el 2004 el de MapReduce, però el codi era propietari. Doug Cutting i Mike Cafarella van crear Hadoop el 2006 com a reimplementació open source d'aquests conceptes mentre treballaven en el motor de cerca Nutch. Yahoo va ser el primer gran usuari, utilitzant Hadoop per indexar la web amb un clúster de 10.000 màquines.
Avui, el 2025, l'ecosistema Hadoop ha evolucionat enormement. MapReduce ja no és l'eina de processament principal (Spark l'ha substituït àmpliament), però HDFS i YARN segueixen sent la base de moltes plataformes de Big Data on-premise. A més, Apache Kafka s'ha convertit en l'espina dorsal del streaming de dades a escala empresarial, independent de Hadoop.
HDFS: Hadoop Distributed File System
Arquitectura
HDFS és un sistema de fitxers distribuït dissenyat per emmagatzemar fitxers molt grans de forma fiable a través d'un clúster de màquines commodity (ordinadors de baix cost estàndard).
graph TB
subgraph Client
C[Client HDFS]
end
subgraph Master
NN[NameNode\nMetadades\nEspai de noms\nDirectori de blocs]
SN[Secondary NameNode\nCheckpoints\nNO es backup!]
NN -.->|checkpoint periodic| SN
end
subgraph Workers
DN1[DataNode 1\nBloc A1\nBloc B2\nBloc C1]
DN2[DataNode 2\nBloc A2\nBloc B1\nBloc C3]
DN3[DataNode 3\nBloc A3\nBloc B3\nBloc C2]
DN4[DataNode 4\nBloc A1 rep\nBloc B2 rep]
end
C -->|1. On estic bloc X?| NN
NN -->|2. DataNode 2, port 50010| C
C -->|3. Llegir dades directament| DN2
DN1 -.->|heartbeat cada 3s| NN
DN2 -.->|heartbeat cada 3s| NN
DN3 -.->|heartbeat cada 3s| NN
Components principals:
NameNode: el "cervell" del clúster HDFS. Emmagatzema tots els metadades del sistema de fitxers: l'arbre de directoris, els permisos, i la llista de blocs que formen cada fitxer i quins DataNodes els contenen. NO emmagatzema les dades reals. El NameNode és l'únic punt de fallada (SPOF) en la configuració bàsica, per la qual cosa Hadoop 2+ suporta High Availability amb dos NameNodes (actiu i de reserva).
DataNode: on es guarden físicament els blocs de dades. Cada DataNode envia un "heartbeat" al NameNode cada 3 segons per indicar que està viu. Si el NameNode no rep heartbeat durant 10 minuts, considera el DataNode mort i replica els seus blocs en altres DataNodes per mantenir el factor de replicació.
Secondary NameNode: NOM és un backup del NameNode! És un servei que periòdicament fa un checkpoint de l'estat del NameNode, fusionant el fitxer fsimage (estat del sistema de fitxers) amb el edits log (canvis recents) per evitar que el log creixi indefinidament.
Blocs i replicació
Per defecte, HDFS divideix cada fitxer en blocs de 128 MB (configurable) i emmagatzema 3 còpies de cada bloc en DataNodes diferents (factor de replicació 3). La política de placement per defecte intenta: - Posar la primera còpia al DataNode on s'escriu - La segona còpia en un rack diferent - La tercera còpia en un altre DataNode del segon rack
Això garanteix que si falla tot un rack (tall de corrent, error de switch), les dades segueixen disponibles.
Càlcul d'espai:
Espai físic necessari = Mida de les dades × Factor de replicació
Exemple:
- Dataset: 10 TB
- Factor replicació: 3
- Espai físic necessari: 10 TB × 3 = 30 TB
- Amb un 20% de marge operatiu: 36 TB
Operacions HDFS bàsiques
# Llistar el directori arrel
hdfs dfs -ls /
# Crear un directori
hdfs dfs -mkdir -p /user/alumne/dades
# Pujar un fitxer local a HDFS
hdfs dfs -put fitxer_local.csv /user/alumne/dades/
# Descarregar un fitxer d'HDFS
hdfs dfs -get /user/alumne/dades/fitxer_local.csv ./
# Veure el contingut d'un fitxer (com cat)
hdfs dfs -cat /user/alumne/dades/fitxer_local.csv | head -20
# Copiar dins HDFS
hdfs dfs -cp /user/alumne/dades/a.csv /user/alumne/backup/
# Esborrar un fitxer (va a la paperera per defecte)
hdfs dfs -rm /user/alumne/dades/fitxer_vell.csv
# Esborrar un directori i tot el seu contingut
hdfs dfs -rm -r /user/alumne/dades_velles/
# Veure l'ús de disc
hdfs dfs -du -s -h /user/alumne/
# Informació del sistema de fitxers
hdfs dfsadmin -report
# Comprovar l'estat del sistema (safe mode, blocs sub-replicats)
hdfs dfsadmin -safemode get
# Balancejar les dades entre DataNodes
hdfs balancer -threshold 10
Safe Mode
En iniciar-se, el NameNode entra en "safe mode" mentre verifica que té prou blocs reportats pels DataNodes. En safe mode, HDFS és de lectura i no permet modificacions. Si un clúster es queda en safe mode indefinidament, pot indicar un problema de DataNodes amb blocs perduts.
HDFS en alta disponibilitat
Per a entorns de producció, HDFS HA usa: - Dos NameNodes: un actiu (active) i un standby - JournalNodes: un quorum de nodes (mínim 3) que emmagatzemen el log d'edicions compartit - ZooKeeper: per a l'elecció automàtica del NameNode actiu i el failover
MapReduce: el paradigma original
MapReduce és un model de programació per al processament distribuït de grans datasets. Inspirat en les funcions funcionals map i reduce, simplifica el processament distribuït amagant tota la complexitat de la distribució, la tolerància a fallades i la gestió de la xarxa.
Com funciona
Dataset gran (TB):
[record1, record2, ..., record_N]
FASE MAP (paral·lela, un mapper per split):
Mapper 1: record1 → [(clau_A, val1), (clau_B, val2)]
Mapper 2: record2 → [(clau_A, val3), (clau_C, val4)]
Mapper N: record_N → [(clau_B, val5), (clau_C, val6)]
FASE SHUFFLE & SORT (framework automàtic):
Agrupa per clau:
clau_A → [val1, val3]
clau_B → [val2, val5]
clau_C → [val4, val6]
FASE REDUCE (un reducer per clau o grup):
Reducer 1: clau_A, [val1, val3] → resultat_A
Reducer 2: clau_B, [val2, val5] → resultat_B
Reducer 3: clau_C, [val4, val6] → resultat_C
Exemple: WordCount en Python (Hadoop Streaming)
#!/usr/bin/env python3
# mapper.py - compta les paraules d'un text
import sys
for linia in sys.stdin:
linia = linia.strip()
paraules = linia.split()
for paraula in paraules:
# Emet (paraula, 1) per a cada paraula
print(f"{paraula.lower()}\t1")
#!/usr/bin/env python3
# reducer.py - suma les ocurrències de cada paraula
import sys
paraula_actual = None
comptador = 0
for linia in sys.stdin:
linia = linia.strip()
paraula, count = linia.split('\t', 1)
count = int(count)
if paraula == paraula_actual:
comptador += count
else:
if paraula_actual is not None:
print(f"{paraula_actual}\t{comptador}")
paraula_actual = paraula
comptador = count
# Emet l'última paraula
if paraula_actual:
print(f"{paraula_actual}\t{comptador}")
# Executar el job MapReduce amb Hadoop Streaming
hadoop jar $HADOOP_HOME/share/hadoop/tools/lib/hadoop-streaming-*.jar \
-input /user/alumne/text_entrada/ \
-output /user/alumne/wordcount_resultat/ \
-mapper mapper.py \
-reducer reducer.py \
-file mapper.py \
-file reducer.py
Quan NO usar MapReduce
MapReduce té limitacions importants que el fan inadequat per a molts casos d'ús moderns:
- Iteracions: algoritmes com k-means o PageRank requereixen múltiples passades sobre les dades. Cada iteració MapReduce escriu i llegeix d'HDFS, introduint una latència enorme.
- Interactivitat: no és possible fer una consulta ad-hoc amb MapReduce en segons; cada job triga minuts.
- Streaming: MapReduce és inherentment batch; no pot processar dades en temps real.
- Complexitat de programació: expressar lògica complexa en parells Map/Reduce és laboriós.
Per a tots aquests casos, Apache Spark (que llegeix de HDFS però processa en memòria) és la solució actual.
YARN: Yet Another Resource Negotiator
YARN és el sistema de gestió de recursos d'Hadoop 2+. Desacobla la gestió de recursos del model de programació, permetent executar no només jobs MapReduce sinó qualsevol framework de computació distribuïda (Spark, Flink, Tez...).
graph TB
subgraph YARN
RM[ResourceManager\nGestiona recursos globals\nPlanífica aplicacions]
NM1[NodeManager 1\nGestiona contenidors\nMonitora recursos]
NM2[NodeManager 2\nGestiona contenidors\nMonitora recursos]
NM3[NodeManager 3\nGestiona contenidors\nMonitora recursos]
end
subgraph App["Aplicacio Spark"]
AM[ApplicationMaster\ns'executa en un contenidor\nNegoci recursos amb RM]
E1[Executor 1]
E2[Executor 2]
end
Client --> RM
RM --> NM1
RM --> NM2
RM --> NM3
NM1 --> AM
NM2 --> E1
NM3 --> E2
AM -->|sol·licita contenidors| RM
Conceptes clau YARN: - Container: unitat de recursos assignada (CPU + memòria) - ApplicationMaster: un procés per aplicació que negocia els recursos amb el ResourceManager - NodeManager: el "daemon" que s'executa a cada worker node i gestiona els contenidors locals
L'Ecosistema Hadoop: les eines complementàries
Apache Hive
Hive és una capa de SQL sobre HDFS/Hadoop que permet fer consultes en SQL (HiveQL) sense programar MapReduce manualment. Tradueix automàticament les consultes SQL en jobs MapReduce o Spark (Hive on Spark).
-- Crear una taula externa sobre dades en HDFS (no copia les dades)
CREATE EXTERNAL TABLE IF NOT EXISTS logs_web (
timestamp_event STRING,
ip_client STRING,
metode STRING,
url STRING,
codi_resposta INT,
mida_resposta BIGINT,
user_agent STRING
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
STORED AS TEXTFILE
LOCATION '/user/alumne/logs/';
-- Crear una taula optimitzada en format Parquet amb particionament
CREATE TABLE logs_web_parquet (
timestamp_event STRING,
ip_client STRING,
metode STRING,
url STRING,
codi_resposta INT,
mida_resposta BIGINT
)
PARTITIONED BY (any INT, mes INT)
STORED AS PARQUET;
-- Carregar dades de la taula original a la particionada
INSERT INTO TABLE logs_web_parquet PARTITION (any=2025, mes=3)
SELECT timestamp_event, ip_client, metode, url, codi_resposta, mida_resposta
FROM logs_web
WHERE year(timestamp_event) = 2025 AND month(timestamp_event) = 3;
-- Anàlisi: top 10 URLs més visitades el 2025
SELECT url, COUNT(*) AS visites
FROM logs_web_parquet
WHERE any = 2025 AND codi_resposta = 200
GROUP BY url
ORDER BY visites DESC
LIMIT 10;
Apache HBase
HBase és una base de dades NoSQL columnar distribuïda sobre HDFS, inspirada en Google Bigtable. Les seves característiques:
- Latència molt baixa per a lectures i escriptures aleatòries (mil·lisegons)
- Escalabilitat horitzontal: pot gestionar trilions de files i milions de columnes
- Consistència forta: a diferència de Cassandra, HBase garanteix consistència en cada lectura
Casos d'ús típics: historial de navegació web, feeds de xarxes socials, missatgeria, registres de trucades (CDR en telecomunicacions).
Apache Sqoop
Sqoop (SQL-to-Hadoop) és l'eina estàndard per a importar dades de bases de dades relacionals (MySQL, Oracle, PostgreSQL) a HDFS o Hive, i viceversa. Usa JDBC internament i paral·lelitza la importació.
# Importar tota una taula de MySQL a HDFS en format Parquet
sqoop import \
--connect jdbc:mysql://servidor-mysql:3306/ecommerce \
--username admin --password secret \
--table comandes \
--target-dir /user/alumne/comandes/ \
--as-parquetfile \
--num-mappers 8 \
--split-by id_comanda
# Exportar dades d'HDFS a MySQL
sqoop export \
--connect jdbc:mysql://servidor-mysql:3306/reporting \
--username admin --password secret \
--table resum_vendes_mensuals \
--export-dir /user/alumne/resum_vendes/ \
--input-fields-terminated-by ','
Sqoop el 2025
Sqoop està en mode de manteniment i no s'actualitza activament. Les alternatives modernes són Apache Nifi per a la ingestió en temps real i Kafka Connect amb connectors JDBC per a la captura de canvis (CDC). Per a migracions batch, moltes empreses usen directament connectors JDBC de Spark.
Apache Oozie
Oozie és el planificador de fluxos de treball (workflow scheduler) natiu de l'ecosistema Hadoop. Permet definir pipelines de jobs MapReduce, Spark i Hive com a grafs DAG en XML. El 2025, ha estat pràcticament substituït per Apache Airflow en noves implantacions.
Apache ZooKeeper
ZooKeeper és un servei de coordinació distribuïda que proporciona: - Configuració distribuïda: emmagatzemar i distribuir configuració entre nodes del clúster - Naming service: descoberta de serveis en un clúster - Sincronització: locks distribuïts per coordinar processos concurrents - Elecció de líder: determinar quin node és el mestre (usat per HBase, YARN HA, Kafka antic)
Apache Kafka: l'espina dorsal del streaming 2025
Visió general
Apache Kafka és una plataforma de streaming distribuïda creada per LinkedIn el 2011. El 2025 és la tecnologia de streaming de dades dominant a l'empresa moderna: Netflix, Uber, Airbnb, LinkedIn (el creador!), Twitter i milers d'empreses el fan servir com a "sistema nerviós central" per a la comunicació entre microserveis i l'ingesta de dades en temps real.
Kafka no és simplement una cua de missatges (com RabbitMQ o ActiveMQ). És una plataforma de streaming de dades que ofereix:
- Alta throughput: milions de missatges per segon en un sol clúster
- Persistència: els missatges s'emmagatzemen en disc (no s'eliminen en ser consumits)
- Replicació: tolerància a fallades via replicació entre brokers
- Retrocés en el temps: els consumidors poden rellegir missatges antics (configurable fins a X dies)
- Escalabilitat horitzontal: afegir particions i brokers per escalar
Arquitectura Kafka
graph LR
subgraph Productors
P1[Microservei\nComandes]
P2[Aplicacio\nWeb - Events]
P3[Sensor\nIoT]
end
subgraph Kafka Cluster
subgraph Topic vendes - 3 particions
T1P0[Particio 0\nBroker 1\nLider]
T1P1[Particio 1\nBroker 2\nLider]
T1P2[Particio 2\nBroker 3\nLider]
end
end
subgraph Consumidors
CG1A[Consumer Group\nAnalytics - Consumer A]
CG1B[Consumer Group\nAnalytics - Consumer B]
CG2[Consumer Group\nFrau - Consumer]
CG3[Consumer Group\nStorage - Consumer]
end
P1 --> T1P0
P2 --> T1P1
P3 --> T1P2
T1P0 --> CG1A
T1P1 --> CG1B
T1P2 --> CG2
T1P0 --> CG3
Conceptes clau:
Topic: una categoria lògica de missatges. Pot tenir un nom arbitrari (vendes, events-usuari, telemetria-sensors). Cada topic es divideix en particions.
Partició: la unitat d'escalabilitat de Kafka. Cada partició és una cua ordenada i immutable de missatges. Més particions = més paral·lelisme = major throughput.
Broker: un servidor Kafka. Un clúster té típicament 3 a N brokers. Cada partició té un broker lider (que gestiona les lectures i escriptures) i N-1 seguidors (rèpliques).
Productor: una aplicació que escriu missatges en un topic. Pot especificar una clau (key) per garantir que missatges amb la mateixa clau sempre van a la mateixa partició (i, per tant, es processen en ordre).
Consumidor: una aplicació que llegeix missatges d'un o més topics. Els consumidors s'agrupen en Consumer Groups: cada missatge es lliura a exactament un consumidor del grup, permetent el processament paral·lel.
Offset: la posició d'un missatge dins d'una partició. Kafka emmagatzema el offset de cada consumer group per saber on va cada grup en la seva lectura.
Exemple pràctic: productor i consumidor Kafka en Python
# productor_kafka.py
from kafka import KafkaProducer
import json
import time
import random
from datetime import datetime
producer = KafkaProducer(
bootstrap_servers=['localhost:9092'],
value_serializer=lambda v: json.dumps(v).encode('utf-8'),
key_serializer=lambda k: k.encode('utf-8') if k else None
)
def generar_event_compra():
"""Genera un event de compra simulat"""
return {
"id_comanda": random.randint(100000, 999999),
"id_usuari": random.randint(1, 10000),
"producte": random.choice(["laptop", "teclat", "monitor", "ratolí", "auriculars"]),
"preu": round(random.uniform(10, 2000), 2),
"timestamp": datetime.now().isoformat(),
"pais": random.choice(["ES", "FR", "DE", "IT", "PT"])
}
# Enviar 100 events de compra
for i in range(100):
event = generar_event_compra()
# Usar l'id_usuari com a clau per garantir ordre per usuari
producer.send(
topic='vendes',
key=str(event['id_usuari']),
value=event
)
print(f"Enviat: {event}")
time.sleep(0.1)
producer.flush()
producer.close()
# consumidor_kafka.py
from kafka import KafkaConsumer
import json
consumer = KafkaConsumer(
'vendes',
bootstrap_servers=['localhost:9092'],
group_id='analytics-group',
auto_offset_reset='earliest', # Llegir des del principi si no hi ha offset guardat
value_deserializer=lambda m: json.loads(m.decode('utf-8')),
key_deserializer=lambda k: k.decode('utf-8') if k else None
)
total_vendes = 0
comptador_per_pais = {}
print("Consumidor iniciat. Esperant missatges...")
for missatge in consumer:
event = missatge.value
total_vendes += event['preu']
pais = event['pais']
comptador_per_pais[pais] = comptador_per_pais.get(pais, 0) + 1
print(f"Particio: {missatge.partition}, Offset: {missatge.offset}")
print(f"Usuari {event['id_usuari']} ha comprat {event['producte']} per {event['preu']}€")
print(f"Total acumulat: {total_vendes:.2f}€ | Vendes per pais: {comptador_per_pais}")
print("---")
# docker-compose.yml per a iniciar Kafka localment
version: '3.8'
services:
zookeeper:
image: confluentinc/cp-zookeeper:7.5.0
container_name: zookeeper
environment:
ZOOKEEPER_CLIENT_PORT: 2181
ZOOKEEPER_TICK_TIME: 2000
kafka:
image: confluentinc/cp-kafka:7.5.0
container_name: kafka
depends_on:
- zookeeper
ports:
- "9092:9092"
environment:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
KAFKA_AUTO_CREATE_TOPICS_ENABLE: 'true'
kafka-ui:
image: provectuslabs/kafka-ui:latest
container_name: kafka-ui
ports:
- "8080:8080"
environment:
KAFKA_CLUSTERS_0_NAME: local
KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka:9092
depends_on:
- kafka
# Iniciar el clúster
docker compose up -d
# Crear un topic manualment (opcional, Kafka pot crear-lo automàticament)
docker exec kafka kafka-topics --create \
--bootstrap-server localhost:9092 \
--topic vendes \
--partitions 3 \
--replication-factor 1
# Llistar topics
docker exec kafka kafka-topics --list --bootstrap-server localhost:9092
# Veure la descripció d'un topic
docker exec kafka kafka-topics --describe \
--bootstrap-server localhost:9092 \
--topic vendes
# Consumir missatges des del terminal (per debugging)
docker exec kafka kafka-console-consumer \
--bootstrap-server localhost:9092 \
--topic vendes \
--from-beginning
Miniactivitat
Inicia el docker-compose.yml anterior, executa el productor i el consumidor en dues terminals separades i observa el flux de missatges. Modifica el productor per enviar events amb preus aleatoris i el consumidor per mostrar l'alerta quan el preu superi 1000€.
Hadoop vs Spark vs Flink: quan usar cada eina
graph LR
subgraph Casos["Cas d'us"]
B1[Batch\nHistoric gran]
B2[Batch\nIteratiu]
B3[Near real-time]
B4[Real-time\nstrict]
B5[ML distribuit]
B6[Grafos]
end
subgraph Eines
MR[MapReduce]
SP[Spark]
FL[Flink]
KS[Kafka Streams]
end
B1 -->|adequat| MR
B1 -->|millor opcio| SP
B2 -->|NO adequat| MR
B2 -->|ideal| SP
B3 -->|Structured Streaming| SP
B3 -->|ideal| FL
B4 -->|NO| SP
B4 -->|ideal latencia ms| FL
B4 -->|simple| KS
B5 -->|MLlib| SP
B6 -->|GraphX| SP
Resum de la decisió:
| Eina | Millor per a | Latència | Complexitat |
|---|---|---|---|
| MapReduce | ETL batch molt gran, compatibilitat legacy | Minuts/hores | Alta (Java) |
| Spark | Batch, ML, streaming near-real-time | Segons/minuts | Mitjana (Python) |
| Flink | Streaming real-time, event-time processing | Mil·lisegons | Alta (Java/Scala) |
| Kafka Streams | Streaming simple en microserveis Java | Mil·lisegons | Baixa (Java) |
Cloud-native Big Data
AWS EMR (Elastic MapReduce)
AWS EMR és un servei gestionat que permet executar Hadoop, Spark, Hive i altres eines de l'ecosistema Big Data sense gestionar la infraestructura manualment.
# Crear un clúster EMR amb Spark
aws emr create-cluster \
--name "Cluster-Analytics-2025" \
--release-label emr-7.0.0 \
--applications Name=Spark Name=Hive Name=Hadoop \
--instance-type m5.xlarge \
--instance-count 5 \
--use-default-roles \
--ec2-attributes KeyName=la-teva-clau \
--auto-terminate
# Submetre un job Spark a EMR
aws emr add-steps \
--cluster-id j-XXXXXXXXXX \
--steps Type=Spark,Name="Analisi Vendes",\
ActionOnFailure=CONTINUE,\
Args=[--deploy-mode,cluster,\
s3://bucket/codi/analisi_vendes.py,\
--input,s3://bucket/dades/,\
--output,s3://bucket/resultats/]
Google Dataproc
L'equivalent de Google Cloud, conegut per la seva velocitat d'aprovisionament (clústers disponibles en 90 segons) i la seva integració nativa amb BigQuery, Cloud Storage i Vertex AI.
Azure HDInsight
La plataforma de Microsoft per a Big Data, integrada amb Azure Data Lake Storage Gen2 i Synapse Analytics.
Databricks
Databricks, fundada pels creadors de Spark i Delta Lake, ofereix el que molts consideren la plataforma de Big Data més completa del 2025. Disponible a AWS, Azure i GCP, ofereix:
- Clusters Spark gestionats amb autoscaling
- Databricks Runtime (versió optimitzada de Spark)
- Delta Lake integrat nativament
- Unity Catalog: governança unificada de dades i ML
- Databricks SQL: SQL Warehouse per a analytics
- MLflow: plataforma de ML integrada
- Notebooks col·laboratius (com Jupyter però més potents)
Miniactivitat
Accedeix a Databricks Community Edition (gratuït: community.cloud.databricks.com) i crea un notebook PySpark que llegeixi les dades del dataset de vols de airlines (disponible a Databricks Datasets) i calculi els retards mitjans per aerolínia.
Exercici pràctic: commandaments HDFS + Hive
Escenari
Tens accés a un clúster Hadoop Docker (o pots usar la imatge bde2020/hadoop-namenode). Has de:
- Preparar les dades localment:
# Descarregar dataset de vendes públic (exemple)
curl -L "https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv" \
-o titanic.csv
# Iniciar el contenidor Hadoop
docker run -d --name hadoop-demo \
-p 9870:9870 -p 8088:8088 \
-e CLUSTER_NAME=demo \
bde2020/hadoop-namenode:2.0.0-hadoop3.2.1-java8
- Pujar dades a HDFS:
# Entrar al contenidor
docker exec -it hadoop-demo bash
# Crear directori a HDFS
hdfs dfs -mkdir -p /user/alumne/titanic
# Pujar el CSV (suposem que l'hem copiat al contenidor)
docker cp titanic.csv hadoop-demo:/tmp/
hdfs dfs -put /tmp/titanic.csv /user/alumne/titanic/
# Verificar
hdfs dfs -ls /user/alumne/titanic/
hdfs dfs -du -h /user/alumne/titanic/
- Crear taula Hive i fer consultes:
-- Iniciar Hive
hive
-- Crear base de dades
CREATE DATABASE IF NOT EXISTS exercici;
USE exercici;
-- Crear taula externa sobre el CSV d'HDFS
CREATE EXTERNAL TABLE passatgers_titanic (
PassengerId INT,
Survived INT,
Pclass INT,
Name STRING,
Sex STRING,
Age DOUBLE,
SibSp INT,
Parch INT,
Ticket STRING,
Fare DOUBLE,
Cabin STRING,
Embarked STRING
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
STORED AS TEXTFILE
LOCATION '/user/alumne/titanic/'
TBLPROPERTIES ("skip.header.line.count"="1");
-- Taxa de supervivència per classe i sexe
SELECT
Pclass AS classe,
Sex AS sexe,
COUNT(*) AS total,
SUM(Survived) AS supervivents,
ROUND(SUM(Survived) * 100.0 / COUNT(*), 1) AS taxa_supervivencia
FROM passatgers_titanic
WHERE Age IS NOT NULL
GROUP BY Pclass, Sex
ORDER BY Pclass, Sex;
-- Edat mitjana dels supervivents vs no supervivents
SELECT
CASE WHEN Survived = 1 THEN 'Supervivent' ELSE 'No supervivent' END AS estat,
ROUND(AVG(Age), 1) AS edat_mitjana,
ROUND(AVG(Fare), 2) AS tarifa_mitjana
FROM passatgers_titanic
WHERE Age IS NOT NULL
GROUP BY Survived;
Preguntes de reflexió:
- Quina diferència hi ha en el rendiment si converteixes el CSV a format Parquet i repeteixes les consultes?
- Quin impacte tindria augmentar el factor de replicació de 3 a 5 en aquest clúster d'un sol node?
- Com modificaries el disseny de la taula Hive per optimitzar les consultes per rang de dates si afegíssim una columna de data?
Consulta el fitxer ../bigdata_aplicat/practiques/practica_hadoop.md per a la pràctica completa de Hadoop amb Docker.