collect操作,在最后的ResultTask.runTask中,执行的function的操作为下面代码.
由于对ResultTask的runTask这个函数的返回值就是这个runTask函数在执行完成RDD传入的function后的返回值.这里要说明下如果task的结果超过了spark.driver.maxResultSize配置的最大值时,默认是1G,直接对task的结果进行丢掉,不处理,
def collect(): Array[T] = withScope {
val results = sc.runJob(this, (iter: Iterator[T]) => iter.toArray)
这个操作把所有的task返回的array进行连接,合并到一个array中进行返回.
Array.concat(results: _*)
}
用于在driver端处理各个Task的结果返回的resultHandler函数,这个函数就是把对应的task的结果直接放到driver端接收数据的一个数组中.
val results = new Array[U](partitions.size)
(index, res) => results(index) = res
在这个操作中,是直接把每个partition中Iterator的结果转换成一个array.上面的红色部分((iter: Iterator[T]) => iter.toArray).
从上面的代码中可以看出来,针对一个rdd的collect的操作是把当前的rdd中所有的partition中的数据集的iterator直接转换成一个array[T],这个array也是对应此partition的返回值,使用collect时要确保每个task的返回的数据的大小,同时要保证所有的task中返回的数据的大小不能超过1GB.
在driver端接收到每一个task返回的数据集时,每个task返回的是这个task中所有的数据集的数组,通过在driver端定义的一个results数组,这个数组的长度就是partition的个数,每个task的返回结果存储到这个对应的index位置上((index, res) => results(index) = res),最后在把这个二维的数据进行concat操作( Array.concat(results: _*)),把所有的数据集合并到一个数组中.这个数组就是执行collect的最终的返回值.