spark源码action系列-reduce

RDD.reduce

这个action的作用:

在reduce中,是把rdd中所有的task中的结果合并成一个结果,最终输出这个结果.这个类似于一个count操作.在reduce中,传入的函数传入两个T类型的参数(T类型是RDD中KV的类型),这个函数返回值也是一个T类型的结果.注意,很多同学会把这个跟hadoop中的map reduce中的reduce进行等同看待,其实不是的,在map reduce中的reduce更像是spark中的一个groupByKey的操作,spark中的reduce只返回一个值,这个值是执行REDUCE操作的RDD中KV的类型.

在reduce的实现内部,定义了两个函数来进行处理.

 

def reduce(f: (TT) => T): withScope {

 

1,这里定义了每个partition的task的执行函数,主要是对iterator进行迭代,

1,先计算f(a1,a2) ,其中f是一个函数,得到一个T类型的值tmpa..

2,接着根据迭代,计算 tmpa与a3的值,得到一个T类型的值tmpa,,,以后按这个方法一直做,直到iterator迭代完成.
  val cleanF = sc.clean(f)
  val reducePartition: Iterator[T] => Option[T] = iter => {
    if (iter.hasNext) {
      Some(iter.reduceLeft(cleanF))
    } else {
      None
    }
  }

 

这个函数是driver端的resultHandler函数,用于把所有的task返回的T类型的值进行合并,合并的方法一样,还是通过上面定义的f函数来进行.
  var jobResult: Option[T] = None
  val mergeResult = (index: InttaskResult: Option[T]) => {
    if (taskResult.isDefined) {
      jobResult = jobResult match {
        case Some(value) => Some(f(valuetaskResult.get))
        case None => taskResult
      }
    }
  }

这里是执行这个任务
  sc.runJob(thisreducePartitionmergeResult)

 

最后,返回合并的T类型的值,所有的task都合并成一个值,如果这个值是null,会出错.也就是说,如果要执行reduce操作,那么这个RDD中必须是一个有数据集的RDD.
  // Get the final result out of our Option, or throw an exception if the RDD was 

      empty
  jobResult.getOrElse(throw new UnsupportedOperationException("empty collection"))
}

 

操作示例:

Rdd中存储的key的类型为用户名称,value是访问过的站点,现在要计算用户是张三这哥们的访问所有站点的总次数,只返回张三这哥们的总次数(这哥们比较NB),其它的用户不统计.

Rdd.filter(kv => kv._1 == 张三).map(kv => kv._1 -> 1).reduce((kv1,kv2) => {

  kv1._2 += kv2._2

})

你可能感兴趣的:(spark源码分析,spark-transform)