Module 7
Module 7
Apache Spark: Ecosystem, components of the Spark context, Spark stage, Spark executor
Spark supports multiple programming languages including Java, Scala, Python, and R,
enabling a wide range of users: data engineers, data scientists, and analysts to leverage its
capabilities. Spark can process data stored in various sources like HDFS, Apache Cassandra,
Apache HBase, Amazon S3 and many more.
A key strength of Spark is its ability to handle iterative algorithms and interactive queries
efficiently by keeping intermediate data in memory, thereby avoiding repeated disk I/O. This
makes Spark up to 100 times faster than Hadoop MapReduce for certain workloads.
Apache Spark Ecosystem Components
The Apache Spark ecosystem is built around the Spark Core, which serves as the foundation
for all Spark functionalities. On top of Spark Core, several specialized libraries enable a wide
variety of data processing tasks. The major components of the Spark ecosystem are:
1. Spark Core: The foundation of Apache Spark, providing essential services like - Task
scheduling, In-memory computation, I/O functionalities and Fault tolerance.
Introduces Resilient Distributed Datasets (RDDs), which are immutable, partitioned
collections of objects distributed across the cluster.
2. Spark SQL: Module for structured data processing, supporting SQL queries and
DataFrame/Dataset APIs. Enables optimizations through Catalyst optimizer and allows
integration with existing Hive tables and various data sources like JSON, Parquet, ORC and
JDBC. Useful for both interactive analytics and batch processing of structured/semi-structured
data.
3. Spark Streaming: Supports real-time data processing from sources such as Kafka, Flume,
Kinesis, TCP sockets and HDFS. Uses micro-batching, converting live data streams into small
batches, which are then processed by the Spark engine. Provides a high-level abstraction
called DStream (Discretized Stream), representing continuous streams as sequences of RDDs.
4. MLlib (Machine Learning Library): A scalable library for machine learning in Spark.
Provides implementations of algorithms for classification, regression, clustering,
collaborative filtering and utilities for feature extraction, transformation, and dimensionality
reduction. The newer DataFrame-based API (from Spark 2.0) is preferred over the older
RDD-based API for user friendliness and integration with Catalyst and Tungsten optimizations.
5. GraphX: API for graph processing and analysis. Provides a directed multigraph
abstraction, extending RDDs to support graph-parallel computation. Supports operations such
as subgraph(), joinVertices(), aggregateMessages(), and algorithms like PageRank,
Connected Components and Triangle Counting.
6. SparkR: R package that allows R users to interact with Spark. Provides SparkR
DataFrames, scalable across multiple cores and nodes. Enables integration with Spark SQL
data sources and benefits from in-memory computation and distributed processing.
2. Partitions: RDDs are split into multiple partitions, each processed independently on
worker nodes. Partitioning enables parallelism and efficient resource utilization.
• Transformations: Lazy operations that define new RDDs from existing ones
(map(), filter(), reduceByKey()).
• Actions: Trigger the execution of transformations and return results
(collect(), count(), saveAsTextFile()).
4. Directed Acyclic Graph (DAG): Spark builds a DAG of stages based on RDD
transformations to optimize execution. DAG ensures fault tolerance and efficient scheduling,
rerunning only affected stages on failure.
3. Executors: Processes running on worker nodes that perform the actual computation.
Executors remain active for the application’s lifetime and handle multiple tasks in parallel.
4. Spark Stage: A physical unit of execution within a Spark job. Contains a set of tasks that
can run in parallel. Defined by the DAGScheduler based on RDD dependencies. Stages are
separated by operations requiring data shuffling (e.g., groupByKey).
5. Tasks: Units of work executed by executors. Each task operates on a single partition of an
RDD or DataFrame.
7. Worker Nodes: Physical machines where executors run. Manage task execution, memory
storage, and communication with the driver.
Example: Filtering words containing "spark" from a list and counting them:
SDD Architecture
The SDD (Spark Distributed Data) Architecture describes how Apache Spark efficiently
stores, manages and processes large-scale data across distributed computing environments. It
ensures fault tolerance, scalability and high performance through an integrated design that
combines storage, data abstraction and distributed execution.
1. Storage Layer
2. Data Layer
• The data layer defines Spark’s logical data abstractions:
o RDD (Resilient Distributed Dataset) – Immutable, distributed collections of
data elements.
o DataFrame – Distributed collections of data with schema information (column
names and types).
o Dataset – Type-safe, object-oriented abstraction combining RDD and
DataFrame benefits.
• These abstractions manage:
o Partitioning – dividing data for parallel processing
o Caching – storing frequently accessed data in memory
o Fault tolerance – using lineage information to recompute lost partitions
• Schema awareness in DataFrames and Datasets allows Catalyst Optimizer to
improve query execution efficiency.
3. Driver Layer
• The Driver Program acts as the central coordinator of the Spark [Link]:
o Initializes SparkContext (for RDD-based API) or SparkSession (for unified
API access).
o Converts user-defined transformations and actions into a Directed Acyclic
Graph (DAG) of stages and tasks.
o Communicates with the Cluster Manager (YARN, Mesos, Kubernetes, or
Standalone) to allocate resources.
o Collects and returns results from worker nodes.
• The Driver also manages job scheduling, task distribution and failure recovery.
4. Execution Flow: The Spark execution flow under the SDD architecture follows these steps:
1. Data Loading: Data resides in external storage (HDFS/S3/etc.) and is loaded into
RDDs or DataFrames.
2. Logical Plan: Transformations and actions applied to data are converted into a logical
DAG by the driver.
3. Physical Plan: The DAG Scheduler splits the computation into stages and each stage
is divided into multiple tasks based on partitions.
4. Execution:
o Tasks are sent to executors on worker nodes.
o Executors perform the assigned computation, store results in memory (if
cached), and write final results back to storage.
5. Result Collection: The driver gathers outputs or writes them to persistent storage.
Feature Description
Data and tasks are distributed across multiple nodes,
Distributed Computation
enabling parallel processing.
Spark uses RDD lineage to recompute lost partitions
Fault Tolerance
automatically.
Intermediate results can be cached in memory, improving
In-memory Computation
iterative processing speeds.
The driver and cluster manager optimize resource use for
Dynamic Resource Allocation
scalability and efficiency.
Supports a wide range of data sources and formats, scaling
Scalability and Flexibility
from a laptop to a cluster.
RDD and RDD Operations – RDD Features and limitations - RDD persistence - Caching
mechanism - DAG
RDD (Resilient Distributed Dataset): An RDD is the fundamental data abstraction in Apache
Spark. It is a distributed collection of immutable objects that can be processed in parallel
across a cluster.
data = [1, 2, 3, 4, 5]
rdd = [Link](data)
print([Link]()) # Output: [1, 2, 3, 4, 5]
rdd = [Link](data, numSlices=3) (we can specify the number of partitions)
2. From external storage (text file, HDFS, S3, etc.): Use [Link]() to read data from
storage into an RDD.
rdd = [Link]("hdfs://namenode:9000/path/[Link]")
RDD Operations: RDD operations are divided into Transformations and Actions:
B. Actions (trigger computation): Actions return a result to the driver program or write data
to storage.
RDD Features
RDD Limitations
RDD Persistence: Persistence allows you to store RDDs in memory or on disk for reuse,
improving performance in iterative operations.
Persistence Levels
Syntax:
[Link](StorageLevel.MEMORY_AND_DISK)
[Link]() # remove from cache
Caching Mechanism
rdd = [Link]("[Link]")
rdd2 = [Link](lambda x: [Link]())
[Link]() # cache the RDD
print([Link]()) # triggers computation
DAG (Directed Acyclic Graph): When transformations is done, Spark does not execute them
immediately. It builds a DAG of stages. DAG represents logical execution plan for RDD
operations. When an action is called, Spark optimizes the DAG and schedules tasks across the
cluster. DAG ensures fault tolerance, because if a partition is lost, Spark can recompute it
from its lineage.
Concept Description
RDD Immutable, distributed collection of objects
Transformations Lazy operations creating new RDDs (map, filter)
Actions Trigger computation (collect, count)
Features Fault-tolerant, in-memory, partitioned, lazy
Limitations No schema, less optimized, manual caching needed
Persistence Store RDD in memory/disk to reuse (persist)
Caching Shortcut for persistence, default MEMORY_ONLY
DAG Logical execution plan; supports fault tolerance & optimization
Apache Spark is a powerful engine for big data processing. When running Spark on a
distributed cluster, cluster management is critical to allocate resources, schedule tasks, and
monitor execution. Spark supports pluggable cluster managers, allowing flexibility
depending on infrastructure and use cases.
a) Standalone Cluster Manager: Simple, built-in cluster manager. Suitable for small-to-
medium clusters.
b) Hadoop YARN (Yet Another Resource Negotiator): Resource manager for the Hadoop
ecosystem. Enables running Spark alongside other Hadoop applications.
o ResourceManager: Global scheduler and application monitor.
o NodeManager: Runs containers for tasks, reports metrics.
o Application Master: Requests resources and executes tasks per application.
• High Availability: Manual via CLI; automatic via ZooKeeper ActiveStandbyElector.
• Security: Kerberos authentication, SSL for data and Web console communication,
ACLs for service access.
• Monitoring: Web UI for ResourceManager and NodeManager metrics.
• Pros: High scalability, robust scheduling, Hadoop integration.
• Cons: Complex setup, overhead from Hadoop ecosystem.
c) Apache Mesos: Distributed cluster manager for multiple frameworks (Spark, Hadoop,
Chronos, Marathon, etc.).
d) Kubernetes
Performance tuning
Spark Performance Tuning is the process of adjusting system settings, resource allocations, and
application code to ensure optimal execution of Spark jobs, avoid bottlenecks, improve
execution time and efficiently utilize resources (CPU, memory, I/O). Spark’s in-memory
computation can lead to resource contention (CPU, memory) if not tuned properly.
Misconceptions about Spark:
Code-Level Optimizations
a. Use DataFrames/Datasets instead of RDDs: Built-in Catalyst optimizer and Tungsten
project enhance performance.
Catalyst Optimizer: Generates efficient execution plans using predicate pushdown, column
pruning and code generation.
Tungsten: Off-heap memory management, binary encoding, and bytecode generation.
d. Broadcast Variables: Efficiently share small, read-only datasets across all worker nodes.
Reduces shuffling and network overhead.
[Link](broadcast(dataset2))
e. Minimize collect() and count() usage: These bring all data to the driver. Use take() or
show() to inspect small samples.
f. Prefilter irrelevant data: Push filters early using predicate pushdown to reduce processing.
g. Reduce UDF usage: UDFs bypass Catalyst optimization and introduce serialization
overhead. Prefer built-in Spark functions or Pandas UDFs when vectorized processing is
needed.
Storage-Level Optimizations
a. Data Serialization: Converts in-memory objects to byte streams for network transfer or
storage.
Java Serialization – Flexible but slow and produces large serialized objects.
Kryo Serialization – Compact, faster, requires class registration:
[Link]("[Link]", "[Link]")
[Link]([MyClass])
Configuration-Level Optimizations
a. Memory Management:
Execution memory: Used for shuffles, joins, aggregations.
Storage memory: Used for caching/persisting data. Unified memory region with dynamic
sharing between execution and storage.
Key parameters:
[Link] (default 0.6) – fraction of JVM heap for Spark memory.
[Link] (default 0.5) – fraction of Spark memory reserved for storage.
d. Shuffle Optimization: Use map-side combiners to reduce shuffle size. Broadcast joins for
small datasets. Tune [Link] based on cluster resources.
e. Parallelism & Level of Concurrency: Ensure high enough parallelism to utilize all cores.
Adjust partitions and cores to balance workload and prevent idle resources.
Advanced Optimization
Adaptive Query Execution (AQE): Dynamically optimize joins, shuffles and skewed data.
Speculative Execution: Mitigates slow tasks by running redundant tasks on other nodes.
Custom partition coalescing: Reduces overhead in stages with narrow transformations.
Predicate pushdown & vectorized reads: For better query performance.
Apache Spark provides multiple abstractions for distributed data processing - RDDs,
DataFrames and Datasets: each evolving to offer higher abstraction, better performance, and
ease of use. These APIs coexist and complement each other, and understanding their
differences helps in selecting the right tool for the job.
1. Resilient Distributed Datasets (RDDs): RDDs are Spark’s fundamental data structure,
introduced in Spark’s first release. They represent an immutable, distributed collection of
objects that can be processed in parallel across a cluster.
Features:
• Immutable and partitioned across nodes.
• Provides low-level control with transformations (map, filter, reduceByKey) and actions
(collect, count, saveAsTextFile).
• Fault-tolerant using lineage information—if data is lost, RDDs can recompute it.
• Supports unstructured and semi-structured data.
Use Cases:
# Create RDD
data = [1, 2, 3, 4, 5]
rdd = [Link](data)
# Transform and filter
rdd2 = [Link](lambda x: x * 2).filter(lambda x: x > 5)
# Collect results
print([Link]())
Limitations:
• No schema enforcement (harder for structured data).
• No built-in query optimization.
• Verbose and lower-level API.
Features:
• Provides SQL-like operations (select, filter, groupBy, join).
• Schema enforcement at runtime.
• Available in Scala, Java, Python, and R.
• Optimized by Catalyst optimizer (logical/physical plan rewriting, predicate
pushdown).
• Executes efficiently via Tungsten engine (code generation, memory management).
Use Cases:
• Working with structured/semi-structured data (CSV, JSON, Parquet, Hive tables).
• SQL-style analytics.
• BI integration (Tableau, Power BI).
• ETL workflows.
• Streaming with Structured Streaming.
Example (Scala):
import [Link]
[Link]()
3. Datasets: Introduced in Spark 1.6, Datasets provide the benefits of RDDs (strong typing,
functional transformations) combined with DataFrame optimizations. They are only available
in Scala and Java.
Features:
• Strongly typed: each row maps to a JVM object (case class in Scala, class in Java).
• Provides compile-time type safety (errors caught before runtime).
• Uses Encoders for efficient serialization.
• Supports both functional transformations (map, flatMap) and SQL-like operations.
Use Cases:
• When working with domain-specific objects.
• Applications requiring compile-time type safety.
• Complex ETL and ML pipelines in Scala/Java.
Example (Scala):
case class Person(name: String, age: Int)
val data = Seq(Person("John", 25), Person("Jane", 30))
val ds = [Link](data)
[Link]()
4. Spark SQL: Spark SQL is the engine powering DataFrames and Datasets.
Example:
[Link]("people")
result = [Link]("SELECT name, age FROM people WHERE age > 30")
[Link]()
Use RDDs: When you need low-level control, unstructured data processing, or iterative
ML/graph algorithms.
Use DataFrames: For most structured and semi-structured workloads, SQL queries, and
ETL pipelines where ease and performance matter.
Use Datasets: When you want type safety and domain-specific object mapping (Scala/Java
only).
In-memory distributed processing using Apache Spark
Big data analytics requires systems that can process massive volumes of data efficiently.
Traditional systems like Hadoop MapReduce rely heavily on disk-based computation,
leading to slower performance due to repeated disk I/O. Apache Spark overcomes this
limitation by enabling in-memory distributed processing, where data is kept in RAM and
processed in parallel across a cluster. This approach accelerates computation, making Spark
especially powerful for iterative algorithms, machine learning, and real-time analytics.
What is Spark In-Memory Computing? In-memory computing means keeping data in RAM
instead of disk drives, enabling faster access and processing.
Key pillars:
• RAM Storage – avoids expensive disk I/O.
• Parallel Distributed Processing – data is partitioned and processed simultaneously
across multiple nodes.
Benefits:
• Faster execution of iterative and interactive queries.
• Economical, as RAM has become more affordable.
• Highly suitable for machine learning, graph processing, and micro-batch stream
processing.
4. Fault Tolerance: Even with in-memory storage, Spark ensures resilience. Uses RDD
lineage to recompute lost data partitions. No explicit replication required unless specified.
5. Parallel Processing: Tasks are distributed across cluster nodes. Multiple partitions
processed concurrently. Combines with in-memory caching for massive performance gains.
rdd = [Link]("[Link]")
[Link]()
# Run multiple transformations without reloading from disk
result = [Link](lambda x: [Link](",")).filter(lambda x: int(x[1]) > 50).count()
Advantages of In-Memory Distributed Processing in Spark
Applications
Spark Shell provides an interactive environment to experiment with Apache Spark. It is very
useful for learning the Spark API, exploring data interactively and testing transformations
and actions before writing full applications. It supports multiple languages:
From a collection:
val data = Array(1, 2, 3, 4, 5)
val rdd = [Link](data)
From a file:
val textFile = [Link]("path/to/[Link]")
Basic Actions
• Count elements: [Link]()
• Collect results: [Link]()
• First element: [Link]()
• Take first n elements: [Link](3)
Basic Transformations
• Cache: [Link]()
• Persist with storage levels:
import [Link]
[Link](StorageLevel.MEMORY_AND_DISK)
• Unpersist (remove from memory): [Link]()
Spark MLlib is Apache Spark’s scalable machine learning library, designed to provide high
performance ML algorithms and tools for large datasets. It makes practical machine
learning scalable, distributed, and easy to use. Works seamlessly with Spark Core, SQL,
Streaming and GraphX, ensuring unified data processing and ML in one platform. Available
in Java, Scala, Python (PySpark) and R. Compared to traditional Hadoop/MapReduce
approaches, Spark MLlib is up to 100x faster for iterative ML tasks due to Spark’s in-memory
computation.
1. ML Algorithms (built-in):
§ Classification: Logistic Regression, Naive Bayes, Decision Trees, Random Forest,
Gradient Boosted Trees, SVMs.
§ Regression: Linear Regression, Generalized Linear Models, Survival Regression.
§ Clustering: K-Means, Gaussian Mixture Models (GMM), Bisecting K-Means.
§ Recommendation: Alternating Least Squares (ALS).
§ Topic Modeling & Mining: Latent Dirichlet Allocation (LDA), frequent itemsets,
association rules, sequential pattern mining.
§ Dimensionality Reduction: PCA, SVD.
2. Feature Engineering:
§ Extraction: TF-IDF, Word2Vec.
§ Transformation: Scaling, normalization, one-hot encoding, hashing.
§ Selection: Chi-squared selector, variance threshold.
4. Utilities:
§ Statistics: summary stats, correlations, hypothesis testing.
§ Linear Algebra: dense/sparse vectors & matrices.
§ Model Evaluation: metrics for classification, regression, clustering.
5. Persistence: Save/load trained models and pipelines for reuse in batch or streaming.
MLlib Architecture
§ Spark Core → Provides RDDs, memory management, and distributed execution.
§ MLlib → Machine learning algorithms and tools.
§ Data Sources → Works with HDFS, Cassandra, Hive, HBase, local files, or cloud
storage.
§ APIs:
o [Link] → RDD-based API (now in maintenance mode).
o [Link] → DataFrame-based API (primary API since Spark 2.0).
6. Deployment
spark = [Link]("MLlibExample").getOrCreate()
# Load dataset
df = [Link]("loan_bank.csv", header=True, inferSchema=True)
# Categorical encoding
categoricalCols = ["job", "marital", "education"]
stages = []
for col in categoricalCols:
indexer = StringIndexer(inputCol=col, outputCol=col+"Index")
encoder = OneHotEncoder(inputCols=[[Link]()],
outputCols=[col+"Vec"])
stages += [indexer, encoder]
# Feature assembler
assemblerInputs = [c+"Vec" for c in categoricalCols] + ["age", "balance", "duration"]
assembler = VectorAssembler(inputCols=assemblerInputs, outputCol="features")
stages += [assembler]
# Model
lr = LogisticRegression(featuresCol="features", labelCol="deposit")
stages += [lr]
# Build pipeline
pipeline = Pipeline(stages=stages)
# Train
pipelineModel = [Link](df)
# Predict
predictions = [Link](df)
[Link]("deposit", "prediction", "probability").show(5)
Advantages of MLlib
§ Scalable: Handles terabytes of data via distributed execution.
§ Fast: Iterative computation in memory (much faster than MapReduce).
§ Integrated: Works with Spark SQL, Streaming, GraphX.
§ Language Flexibility: Java, Scala, Python, R.
§ End-to-End ML: Covers ingestion → preprocessing → training → evaluation →
deployment.
MLlib in Practice
§ Recommendation Engines → Netflix-style ALS recommender.
§ Fraud Detection → Classification on transaction data.
§ Customer Segmentation → Clustering (K-Means/GMM).
§ Predictive Analytics → Regression for demand forecasting.
§ Streaming ML → Use trained models with Structured Streaming for real-time
predictions.