spark core实现了spark的基本功能:存储交互、任务调度、内存管理、错误恢复等;本片文章主要介绍与数据交互相关的核心技术点。
本文目录:
- RDD特性及交互
- shuffle操作及调优
- RDD持久化的应用
- Broadcast Variables&Accumulators共享变量的优势及应用场景
- 下篇预告
RDD特性及交互
弹性分布式数据集(resilient distributed dataset),具备只读、可并行计算、容错性等三个主要特性。
可以由hdfs文件(包含hbase等各类以hdfs为基础的数据源)或者scala集合来创建RDD。
针对RDD,spark提供了两种类型的操作算子:transformations、action
- transformations
主要是基于已有的RDD创建新的RDD,transformations类操作具有惰性(lazy),仅当遇见action操作需要结果时才执行,这个特性也是spark更加高效的原因之一。默认情况下,每一次action都会触发与之相关的transformations,如果一个rdd会多次使用,建议进行持久化或者缓存。
transformations算子
- action
是将在rdd上计算的将结果传给driver program。Job就是根据action算子划分的。
action算子
Shuffle
指的是会引起数据的重分布的操作(re-distributing data);比如:repartition、coalesce、ByKey的操作以及join类别的操作,如:cogroup、join等。stage救赎根据shuffle算子划分的
shuffle操作需要大量的IO、网络IO以及序列化等操作,比较耗资源。
比较老的spark版本采用hash based shuffle(现在以及弃用)方式进行shuffle。举例:3个 map task, 3个 reducer, 会产生 9个小文件,
hash based shuffle
比较新的spark版本采用Consolidated HashShuffle:4个map task, 4个reducer, 如果不使用 Consolidation机制, 会产生 16个小文件。但是但是现在这 4个 map task 分两批运行在 2个core上, 这样只会产生 8个小文件。
Consolidated HashShuffle
shuffle调优方式
- 合理的设置partition数目
- 防止数据倾斜
- 合理配置一些参数,如excutor的内存,网络传输中数据的压缩方式,传输失败的重试次数等。
RDD 持久化
当一个RDD会重复使用时,可以选择持久化来缩短任务执行时间。(但如果数据量不是太大,重新生成RDD的时间消耗小于从磁盘或内存加载的时间时,就不宜持久化)
spark自动管理持久化之后的数据,会结合least-recently-used (LRU)算法删除数据。
持久化有如下几种方式:
RDD持久化
Broadcast Variables&Accumulators共享变量
- Broadcast Variables
针对只读变量的数据共享机制。以比较高效的方式将只读变量共享到所有机器上,当然使用普通变量也能达到类似的效果,但Broadcast类型的变量更加高效,主要具有以下优点。
- broadcast类型变量可以保证只在executor的内存中存在一份,只需要发送一次。普通变量每个task都会发生一次数据传输。
- 将要传输的变量不需要实现Serializable接口
- 可以高效地传输较大的数据集
2. Accumulators
可以理解为一个只能进行加法操作的变量,spark有一些内置类型,如:longAccumulator、doubleAccumulator,用户也可自定义。Task在执行过程中只能调用其add方法,但是不能获取到他的值。只有Driver Progeam可以获取到它的值。常用的场景有计数、求和等。 示例:
val accum = sc.longAccumulator("My Accumulator")
sc.parallelize(Array(1, 2, 3, 4)).foreach(x => accum.add(x))
accum.value
下篇预告
下篇将会介绍spark core的任务调度与容错机制