Apache Spark és un motor de processament de dades distribuït i de codi obert, dissenyat per fer càlculs sobre grans volums de dades de manera ràpida, tant en batch (per lots) com en streaming (temps real). La seva característica principal és el processament en memòria, que el fa molt més ràpid que alternatives com Hadoop MapReduce en molts casos d’ús, especialment els algorismes iteratius.
Va ser creat per Matei Zaharia l’any 2009, a l’AMPLab de la Universitat de Califòrnia, Berkeley, com a projecte de recerca. El 2010 es va publicar com a codi obert, i el 2013 va passar a ser un projecte de l’Apache Software Foundation, on el 2014 va assolir l’estatus de projecte de nivell superior (Top-Level Project).
Spark es distribueix sota la Apache License 2.0, una llicència de programari lliure permissiva que permet l’ús, modificació i distribució (fins i tot comercial) del codi, sense obligar a alliberar les modificacions sota la mateixa llicència (a diferència de llicències copyleft com la GPL).
| Mòdul | Descripció |
|---|---|
| Spark Core | Nucli del motor: gestió de tasques, planificació, i abstraccions bàsiques (RDD, DataFrames, Datasets). Processament distribuït en memòria amb tolerància a fallades |
| Spark SQL | Consultes SQL sobre dades estructurades, amb l’optimitzador de consultes Catalyst i el motor d’execució Tungsten |
| Structured Streaming | Processament de fluxos de dades en temps real (micro-batching), amb la mateixa API que el processament per lots |
| MLlib | Biblioteca de machine learning distribuïda: classificació, regressió, clustering, sistemes de recomanació, reducció de dimensionalitat, pipelines de ML |
| GraphX | Processament i anàlisi de grafs (xarxes socials, algorismes com PageRank) |
| SparkR / PySpark | APIs per treballar amb R i Python, a més de Scala (llenguatge natiu) i Java |
MapReduce escriu resultats intermedis a disc entre cada fase Map i Reduce, cosa que genera molta latència. Spark, en canvi, manté les dades en memòria RAM entre operacions sempre que és possible, cosa que pot arribar a fer-lo 10-100 vegades més ràpid en determinats casos d’ús (especialment algorismes iteratius com machine learning).
RDD (Resilient Distributed Dataset)
- L’estructura de dades original de Spark: col·lecció distribuïda i immutable, tolerant a fallades
- Nivell baix, més control però més verbós.
DataFrames
- Dades organitzades en columnes (com una taula SQL), amb optimitzacions automàtiques via el Catalyst optimizer
- És l’API més utilitzada avui dia.
Datasets
- Combina els avantatges de tipat fort (com RDD) amb les optimitzacions dels DataFrames (disponible principalment a Scala/Java).
Scala (llenguatge natiu de Spark), Python (PySpark, molt popular), Java, i R.
Spark no substitueix HDFS; sovint funciona sobre HDFS com a sistema d’emmagatzematge, i pot executar-se sobre YARN com a gestor de recursos. El que substitueix és el motor de processament MapReduce. Molts clústers moderns són “Hadoop” només pel que fa a HDFS+YARN, però amb Spark com a motor de càlcul principal.
Aquest document explica com desplegar un clúster Spark en mode standalone utilitzant diverses màquines virtuals Ubuntu Server. És un exercici ideal per entendre l’arquitectura master/worker d’un sistema de processament distribuït, sense necessitat de muntar un clúster Hadoop complet.
Es parteix d’un escenari amb 3 VM (spark-master, spark-worker1, spark-worker2), però funciona
igual amb 2 o més nodes. Totes les VM han de tenir connectivitat de
xarxa entre elles.
| Node | Rol | Hostname | IP (exemple) |
|---|---|---|---|
| VM 1 | Master | spark-master | 10.0.2.10 |
| VM 2 | Worker | spark-worker1 | 10.0.2.11 |
| VM 3 | Worker | spark-worker2 | 10.0.2.12 |
El master coordina l’execució dels jobs i exposa una interfície web de monitoratge. Els workers executen les tasques reals i reporten l’estat al master.
Actualitza la llista de paquets:
sudo apt updateActualitza els paquets:
sudo apt upgradeSpark necessita un JDK (recomanat OpenJDK 17):
sudo apt install openjdk-17-jdk/etc/hostsA totes les VMs, afegeix les entrades de tots els nodes perquè es resolguin per nom:
sudo nano /etc/hosts10.0.2.10 spark-master
10.0.2.11 spark-worker1
10.0.2.12 spark-worker2
Crea l’usuari:
sudo adduser sparkAfegeix l’usuari al grup de sudoers:
sudo usermod -aG sudo sparkDes del spark-master, com a usuari spark,
genera un parell de claus SSH:
ssh-keygen -t ed25519Copia la clau pública generada al primer worker:
ssh-copy-id spark@spark-worker1Copia la clau pública generada al segon worker:
ssh-copy-id spark@spark-worker2Això permetrà als scripts start-all.sh/stop-all.sh arrencar i aturar
tots els workers remotament des del master.
Mou-te al directori opt:
cd /optDescarrega Spark:
sudo wget -c https://dlcdn.apache.org/spark/spark-4.2.0/spark-4.2.0-bin-hadoop3.tgzDescomprimeix:
sudo tar -xzf spark-4.2.0-bin-hadoop3.tgzCanvia el nom de la carpeta:
sudo mv spark-4.2.0-bin-hadoop3 sparkCanvia el propietari:
sudo chown -R spark:spark /opt/sparkEsborra el fitxer descarregat:
sudo rm spark-4.2.0-bin-hadoop3.tgzComprova sempre la versió actual a https://spark.apache.org/downloads.html — els números de versió canvien amb el temps i l’enllaç pot quedar desactualitzat.
Edita /etc/profile.d/spark.sh:
sudo nano /etc/profile.d/spark.shexport JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
export SPARK_HOME=/opt/spark
export PATH=$PATH:$SPARK_HOME/bin:$SPARK_HOME/sbin
Dona permís d’execució:
sudo chmod +x /etc/profile.d/spark.shExecuta l’script spark.sh al context (shell) actual:
source /etc/profile.d/spark.shPer què és important fer source i no simplement
executar-lo (./spark.sh o bash spark.sh)? Si executessis l’script
normalment (com a subprocés), les variables que defineix (per exemple
SPARK_HOME, afegir Spark al PATH, JAVA_HOME, etc.) es perdrien en acabar
l’script, ja que només afectarien aquell subprocés. Amb source, aquestes
variables queden exportades a la teva shell actual i, per tant,
disponibles per a les comandes següents (com spark-submit, pyspark,
spark-shell, etc.).
Repeteix aquest pas 2 a totes les VM (master i workers).
workerscd /opt/spark/conf
sudo cp workers.template workers
sudo nano workersSubstitueix el contingut per la llista de workers:
spark-worker1
spark-worker2
spark-env.shsudo cp spark-env.sh.template spark-env.sh
sudo nano spark-env.shAfegeix:
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
export SPARK_MASTER_HOST=spark-master
export SPARK_WORKER_CORES=2
export SPARK_WORKER_MEMORY=2g
Ajusta SPARK_WORKER_CORES i SPARK_WORKER_MEMORY segons els recursos assignats a cada
VM.
Des del spark-master:
$SPARK_HOME/sbin/start-all.shAixò arrenca el master localment i, via SSH, els workers definits al
fitxer workers.
Comprova els processos Java actius:
jpsAl master hauries de veure Master, i a cada worker un
procés Worker.
Sortida esperada al master:
19587 Master
19674 JpsSortida esperada al worker1:
19751 Worker
19819 JpsSortida esperada al worker2:
19939 Jps
19871 WorkerObre al navegador:
http://spark-master:8080Hi veuràs els workers registrats, els cores i memòria disponibles, i els jobs en execució.
Instal·la Python:
sudo apt install python3-pipLlança una shell PySpark connectada al clúster:
pyspark --master spark://spark-master:7077Dins la shell, prova un càlcul distribuït senzill: “Compta quants múltiples de 7 hi ha entre 1 i 1.000.000”
data = range(1, 1000000)
rdd = spark.sparkContext.parallelize(data)
print(rdd.filter(lambda x: x % 7 == 0).count())Crea una seqüència de Python amb els nombres de l’1 a l’1.000.000. Distribueix aquesta seqüència pel clúster d’Spark, creant un RDD (Resilient Distributed Dataset). Les dades es divideixen en particions per poder processar-les en paral·lel. Filtra els nombres divisibles entre 7 i retorna quants elements queden després del filtre.
Un detall important: fins que no es crida count(), Spark
no ha fet realment cap càlcul. Les transformacions només construeixen el
pla d’execució.
Si mires la interfície web (http://spark-master:4040
mentre la shell és oberta), veuràs el job executant-se i repartint-se
entre els workers.
$SPARK_HOME/sbin/stop-all.shPer no haver d’arrencar el clúster manualment cada cop, pots crear una unitat systemd al master:
sudo nano /etc/systemd/system/spark-master.service[Unit]
Description=Apache Spark Master
After=network.target
[Service]
Type=forking
User=spark
ExecStart=/opt/spark/sbin/start-master.sh
ExecStop=/opt/spark/sbin/stop-master.sh
[Install]
WantedBy=multi-user.target
I de forma anàloga a cada worker, amb start-worker.sh spark://spark-master:7077.
sudo systemctl daemon-reload
sudo systemctl enable --now spark-master| Símptoma | Causa probable | Solució |
|---|---|---|
| El worker no apareix a la UI | SSH sense contrasenya no configurat | Revisar ssh-copy-id i permisos ~/.ssh |
JAVA_HOME not set |
Variable no exportada al servei | Afegir JAVA_HOME a spark-env.sh |
| Job es queda “en cua” indefinidament | No hi ha cores/memòria disponibles | Revisar SPARK_WORKER_CORES/SPARK_WORKER_MEMORY |
| No es resol el hostname del master | /etc/hosts incomplet en algun node |
Verificar que totes les VM tenen totes les entrades |