最近在复习spark,写一些笔记来记录复习的源码过程,以及使用一些源码手动实现算子的过程。
map算子
//这是一个简单的map方法Demo
object Demo1 {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setAppName("Demo1").setMaster("local[*]")
val sc = new SparkContext(conf)
val rdd1 = sc.makeRDD(List(1, 2, 3, 4, 5))
val result = rdd1.map(_ + "分")
result.foreach(println)
sc.stop()
}
}
//这里是map的源码
点击map进入
def map[U: ClassTag](f: T => U): RDD[U] = withScope {
val cleanF = sc.clean(f)
new MapPartitionsRDD[U, T](this, (context, pid, iter) => iter.map(cleanF))
}
点击MapPartitionsRDD进入
private[spark] class MapPartitionsRDD[U: ClassTag, T: ClassTag](
var prev: RDD[T],
f: (TaskContext, Int, Iterator[T]) => Iterator[U], // (TaskContext, partition index, iterator)
preservesPartitioning: Boolean = false,
isFromBarrier: Boolean = false,
isOrderSensitive: Boolean = false)
这里传入的参数
prev 父RDD
f 传入TaskContext,就是配置信息,然后传入分区编号,传入一个对迭代器操作的方法,其实就是传入了scala中的map方法。
preservesPartitioning 是否保留分区器,一般都是否。除非是pairRDD并且应用的方法没有改变key。
isFromBarrier 是否来自屏障RDD,这是Spark3中的新特性,好像是和机器学习相关的,没有仔细看
isOrderSensitive
mapPartitions算子
object Demo1 {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setAppName("Demo1").setMaster("local[*]")
val sc = new SparkContext(conf)
val rdd1 = sc.makeRDD(List(1, 2, 3, 4, 5))
val value = rdd1.mapPartitions(it=>it.map(_ + "分"))
sc.stop()
}
}
上边这是一个调用mapPartitions的例子,点进mapParttitions进入源码
def mapPartitions[U: ClassTag](
f: Iterator[T] => Iterator[U],
preservesPartitioning: Boolean = false): RDD[U] = withScope {
val cleanedF = sc.clean(f)
new MapPartitionsRDD(
this,
(context: TaskContext, index: Int, iter: Iterator[T]) => cleanedF(iter),
preservesPartitioning)
}
源码中,sc.clean(f)就是对传入的函数做了一个闭包检查,可以忽略它,把cleandF当成我们自己传入的逻辑就可以了。
可以看到mapPartitions也是新建了一个MapPartitionsRDD,里边就是和map的区别了,
在map中,对迭代器的操作是map(我们自己写的逻辑),
这样就会导致迭代器每次map出一条数据就会调用一次我们传入的逻辑。
而mapPartitions直接调用了我们传入的逻辑,
这样每个分区的迭代器只会调用一次,这样就算迭代器里的逻辑还是调用map,我们传入的逻辑也就只调用了一次。
mapPartitionsWithIndex算子
这个算子其实就是在mapPartitions的基础上把分区索引拿出来了,因为new MapPartition的时候参数就要有分区编号,所以这个算子本质上和mapPartitions没有区别。
filter算子
filter算子其实和map差不多,都是新建了一个MapPartitionsRDD,不过里边对迭代器的操作变成了filter。