IBM Spark Meetup - RDD & Spark Basics
-
Upload
satyanarayan-patel -
Category
Data & Analytics
-
view
444 -
download
3
Embed Size (px)
Transcript of IBM Spark Meetup - RDD & Spark Basics

© 2015 IBM Corporation
RDD Deep Dive• RDD Basics
• How to create • RDD Operations• Lineage
• Partitions • Shuffle • Type of RDDs• Extending RDD• Caching in RDD

© 2015 IBM Corporation
RDD Basics • RDD (Resilient Distributed Dataset)
• Distributed collection of Object • Resilient - Ability to re-compute missing partitions
(node failure)• Distributed – Split across multiple partitions • Dataset - Can contain any type, Python/Java/Scala
Object or User defined Object
• Fundamental unit of data in spark

© 2015 IBM Corporation
RDD Basics – How to create Two ways
Loading external datasets Spark supports wide range of sources Access HDFS data through InputFormat & OutputFormat
of Hadoop. Supports custom Input/Output format
Parallelizing collection in driver program
val lineRDD = sc.textFile(“hdfs:///path/to/Readme.md”)textFile(“/my/directory/*”) or textFile(“/my/directory/*.gz”) SparkContext.wholeTextFiles returns (filename,content) pair
val listRDD = sc.parallelize(List(“spark”,”meetup”,”deepdive”))

© 2015 IBM Corporation
RDD Operations Two type of Operations
Transformation Action
Transformations are lazy, nothing actually happens until an action is called.
Action triggers the computation Action returns values to driver or writes data to external storage.

© 2015 IBM Corporation
Lazy Evaluation Transformation on RDD, don’t get performed immediately
Spark Internally records metadata to track the operation
Loading data into RDD also gets lazy evaluated
Lazy evaluation reduce number of passes on the data by grouping operations
MapReduce – Burden on developer to merge the operation, complex map.
Failure in Persisting the RDD will re-compute complete lineage every time.

© 2015 IBM Corporation
RDD In Action sc.textFile(“hdfs://file.txt") .flatMap(line=>line.split(" ")) .map(word => (word,1)) .reduceByKey(_+_) .collect()
I scream you scream lets all scream for icecream!
I wish I were what I was when I wished I were what I am.
Iscreamyouscreamletsallscream foricecream
(I,1)(scream,1)(you,1)(scream,1)(lets,1)(all,1)(scream,1)(icecream,1)
(icecream,1)
(scream,3)
(you,1)
(lets,1)
(I,1)
(all,1)

© 2015 IBM Corporation
Lineage Demo

© 2015 IBM Corporation
RDD Partition Partition Definition
Fragments of RDD Fragmentation allows Spark to execute in Parallel. Partitions are distributed across cluster(Spark worker)
Partitioning Impacts parallelism Impacts performance

© 2015 IBM Corporation
Importance of partition Tuning Too few partitions
Less concurrency, unused cores. More susceptible to data skew Increased memory pressure for groupBy, reduceByKey,
sortByKey, etc. Too many partitions
Framework overhead (more scheduling latency than the time needed for actual task.)
Many CPU context-switching Need “reasonable number” of partitions
Commonly between 100 and 10,000 partitions Lower bound: At least ~2x number of cores in cluster Upper bound: Ensure tasks take at least 100ms

© 2015 IBM Corporation
How Spark Partitions data
Input data partition Shuffle transformations Custom Partitioner

© 2015 IBM Corporation
Partition - Input Data Spark uses same class as Hadoop to perform Input/Output sc.textFile(“hdfs://…”) invokes Hadoop TextInputFormat Below are Knobs which defines #Partitions
dfs.block.size – default 128MB(Hadoop 2.0) numPartition – can be used to increase number of partition
default is 0 which means 1 partition mapreduce.input.fileinputformat.split.minsize – default 1kb
Partition Size = Max(minsize,Min(goalSize,blockSize) goalSize = totalInputSize/numPartitions 32MB, 0, 1KB, 640MB total size - Defaults
Max(1kb,Min(640MB,32MB) ) = 20 partitions 32MB, 30, 1KB , 640MB total size - Want more partition
Max(1kb,Min(32MB,32MB)) = 32 partition 32MB, 5, 1KB = Max(1kb,Min(120MB,32MB)) = 20 – Bigger size
partition 32MB,0, 64MB = Max(64MB,Min(640MB,32MB)) = 10 Bigger size
partition

© 2015 IBM Corporation
Partition - Shuffle transformations All shuffle transformation provides parameter
for desire number of partition Default Behavior - Spark Uses HashPartitioner.
If spark.default.parallelism is set , takes that as # of partitions
If spark.default.parallelism is not set largest upstream RDD ‘s number of partition Reduces chances of out of memory
1. groupByKey2. reduceByKey3. aggregateByKey4. sortByKey5. join6. cogroup7. cartesian8. coalesce9. repartition10.repartitionAndSortWithinPartitions
Shuffle Transformation

© 2015 IBM Corporation
Partition - Repartitioning RDD provides two operators
repartition(numPartitions) Can Increase/decrease number of partitions Internally does shuffle expensive due to shuffle For decreasing partition use coalesce
Coalesce(numPartition,Shuffle:[true/false]) Decreases partitions Goes for narrow dependencies Avoids shuffle In case of drastic reduction may trigger shuffle

© 2015 IBM Corporation
Custom Partitioner Partition the data according to use case & data structure Custom Partitioning allows control over no of partitions and
distribution of data Extends Partitioner class, need to implement getPartitions &
numPartitons

© 2015 IBM Corporation
Partitioning Demo

© 2015 IBM Corporation
Shuffle - GroupByKey Vs ReduceByKey
val wordCountsWithGroup = rdd .groupByKey() .map(t => (t._1, t._2.sum)) .collect()

© 2015 IBM Corporation
Shuffle - GroupByKey Vs ReduceByKey
val wordPairsRDD = rdd.map(word => (word, 1))val wordCountsWithReduce = wordPairsRDD .reduceByKey(_ + _)
.collect()

© 2015 IBM Corporation
The Shuffle Redistribution of data among partition between stages. Most of the Performance, Reliability Scalability Issues in Spark occurs
within Shuffle. Like MapReduce Spark shuffle uses Pull model. Consistently evolved and still an area of research in Spark

© 2015 IBM Corporation
Shuffle Overview• Spark run job stage by stage.
• Stages are build up by DAGScheduler according to RDD’s ShuffleDependency
• e.g. ShuffleRDD / CoGroupedRDD will have a ShuffleDependency
• Many operator will create ShuffleRDD / CoGroupedRDD under the hood.• Repartition/CombineByKey/GroupBy/ReduceByKey/
cogroup• Many other operator will further call into the above
operators• e.g. various join operator will call CoGroup.
• Each ShuffleDependency maps to one stage in Spark Job and then will lead to a shuffle.

© 2015 IBM Corporation
You have seen this
join
union
groupBy
Stage 3
Stage 1
Stage 2
A:
B:
C:
D:
map
E:
F:
G:

© 2015 IBM Corporation
Shuffle is Expensive
• When doing shuffle, data no longer stay in memory only, gets written to disk.
• For spark, shuffle process might involve• Data partition: which might involve very expensive data
sorting works etc.• Data ser/deser: to enable data been transfer through
network or across processes.• Data compression: to reduce IO bandwidth etc.• Disk IO: probably multiple times on one single data block
• E.g. Shuffle Spill, Merge combine

© 2015 IBM Corporation
Shuffle History Shuffle module in Spark has evolved over time. Spark(0.6-0.7) – Same code path as RDD’s persist method.
MEMORY_ONLY , DISK_ONLY options available. Spark (0.8-0.9)
Separate code for shuffle, ShuffleBlockManager & BlockObjectWriter for shuffle only.
Shuffle optimization - Consolidate Shuffle Write. Spark 1.0 – Introduced pluggable shuffle framework Spark 1.1 – Sort based Shuffle Implementation Spark 1.2 - Netty transfer Implementation. Sort based shuffle is
default now. Spark 1.2+ - External shuffle service etc.

© 2015 IBM Corporation
Understanding Shuffle Input Aggregation Types of Shuffle
Hash based Basic Hash Shuffle Consolidate Hash Shuffle
Sort Based Shuffle

© 2015 IBM Corporation
Input Aggregation Like MapReduce, Spark involves aggregate(Combiner) on map side. Aggregation is done in ShuffleMapTask using
AppendOnlyMap (In Memory Hash Table combiner) Key’s are never removed , values gets updated
ExternalAppendOnlyMap (In Memory and disk Hash Table combiner) A Hash Map which can spill to disk Append Only Map that spill data to disk if insufficient memory
Shuffle file In-Memory Buffer – Shuffle writes to In-memory buffer before writing to a shuffle file.

© 2015 IBM Corporation
Shuffle Types – Basic Hash Shuffle Hash Based shuffle (spark.shuffle.manager). Hash Partitions the data
for reducers Each map task writes each bucket to a file.
#Map Tasks = M #Reduce Tasks = R #Shuffle File = M*R , #In-Memory Buffer = M*R

© 2015 IBM Corporation
Shuffle Types – Basic Hash Shuffle Problem
Lets use 100KB as buffer size We have 10000 reducers 10 Mapper tasks Per Executor In-Memory Buffer size will = 100KB*10000*10 Buffer need will be 10GB/Executor This huge amount of Buffer is not acceptable and this
Implementation cant support 10000 reducer.

© 2015 IBM Corporation
Shuffle Types – Consolidate Hash Shuffle Solution to decrease the IN-Memory Buffer size , No of File. Within Executor, Map Tasks writes each Bucket to a Segment of the file. #Shuffle file/Executor = #Reducers, # In-Memory Buffer/ Executor=#R( Reducers)

© 2015 IBM Corporation
Shuffle Types – Sort Based Shuffle Consolidate Hash Shuffle needs one file for each reducer.
- Total C*R intermediate file , C = # of executor running map tasks
Still too many files(e.g ~10k reducers), Need significant memory for compression & serialization
buffer. Too many open files issue.
Sort Based Shuflle is similar to map-side shuffle from MapReduce
Introduced in Spark 1.1 , now its default shuffle

© 2015 IBM Corporation
Shuffle Types – Sort Based Shuffle Map output records from each task are kept in memory till they can fit. Once full , data gets sorted by partition and spilled to single file. Each Map task generate 1 data file and one index file
Utilize external sorter to do the sort work If map side combiner is required data will be sorted by key and partition
otherwise only by partition #reducer <=200, no sorting uses hash approach, generate file per reducer and
merge them into a single file

© 2015 IBM Corporation
Shuffle Reader On Reader side both Sort & Hash Shuffle uses Hash Shuffle Reader
On reducer side a set of thread fetch remote output map blocks Once block comes its records are de-serialized and passed into a
result queue. Records are passed to ExternalAppendOnlyMap , for ordering
operation like sortByKey records are passed to externalSorter.
20
Bucket
Bucket
Bucket
Bucket
Bucket
Bucket
Bucket
Bucket
Bucket
Bucket
Bucket
Bucket
Bucket
Bucket
Bucket
Bucket
Reduce Task
Aggregator Aggregator Aggregator Aggregator
Reduce Task Reduce Task Reduce Task

© 2015 IBM Corporation
Type of RDDS - RDD Interface
Base for all RDDs (RDD.scala), consists of A Set of partitions (“splits” in Hadoop) A List of dependencies on parent RDDs A Function to compute the partition from its
parents
Optional preferred locations for each partition A Partitioner defines strategy for partitionig
hash/range
Basic operations like map, filter, persist etc
Partitions
Dependencies
Compute
PreferredLocations
Partitioner
map,filter,persists
Lineage
Optimized execution
Operations

© 2015 IBM Corporation
Example: HadoopRDD partitions = one per HDFS block dependencies = none compute(partition) = read corresponding block
preferredLocations(part) = HDFS block location partitioner = none

© 2015 IBM Corporation
Example: MapPartitionRDD partitions = Parent Partition dependencies = “one-to-one “parent RDD compute(partition) = apply map on parent
preferredLocations(part) = none (ask parent) partitioner = none

© 2015 IBM Corporation
Example: CoGroupRDD
partitions = one per reduce task dependencies = could be narrow or wide dependency compute(partition) = read and join shuffled data
preferredLocations(part) = none partitioner = HashPartitioner(numTasks)

© 2015 IBM Corporation
Extending RDDsExtend RDDs to To add Domain specific transformation/actions
Allow developer to express domain specific calculation in cleaner way
Improves code readability Easy to maintain
Domain specific RDD Better way to express domain specific data Better control on partitioning and distribution Way to add new Input data source

© 2015 IBM Corporation
How to Extend Add custom operators to RDD
Use scala Impilicits Feels and works like built in operator You can add operator to Specific RDD or to all
Custom RDD Extend RDD API to create our own RDD Implement compute & getPartitions abstract method

© 2015 IBM Corporation
Implicit Class
Creates an extension method to existing type Introduced in Scala 2.10 Implicits are compile time checked. Implicit class gets resolved
into a class definition with implict conversion We will use Implicit to add new method in RDD

© 2015 IBM Corporation
Adding new Operator to RDD We will use Scala Implicit feature to add a new operator to an
existingRDD This operator will show up only in our RDD Implicit conversions are handled by Scala

© 2015 IBM Corporation
Custom RDD Implementation Extending RDD allow you to create your own custom RDD
structure Custom RDD allow control on computation, change partition &
locality information

© 2015 IBM Corporation
Caching in RDD Spark allows caching/Persisting entire dataset in memory Persisting RDD in cache
First time when it is computed it will be kept in memory Reuse the the cache partition in next set of operation Fault-tolerant, recomputed in case of failure
Caching is key tool for interactive and iterative algorithm Persist support different storage level
Storage level - In memory , Disk or both , Techyon Serialized Vs Deserialized

© 2015 IBM Corporation
Caching In RDD Spark Context tracks persistent RDDs Block Manager puts partition in memory when first evaluated Cache is lazy evaluation , no caching without an action. Shuffle also keeps its data in Cache after shuffle operations.
We still need to cache shuffle RDDs

© 2015 IBM Corporation
Caching Demo