Spark transform操作的非常规使用 - SparkContext.runJob()方法的调用

前文

     一般场景中,Spark计算任务中transform相关的操作都是由action进行触发的,常见的的比如write、collect、show等,或者在数据处理的过程中调用的groupbykey等API,进行shuffle数据重新分发,在提交任务时会把transform的操作作为前置任务进行提交,但是单纯的transform操作是无法触发spark计算任务的。

    但是,单纯由transform API构建的Spark计算任务,应该怎么触发计算任务呢?

    一些场景中会遇到单纯由transforms构成的计算流程,或者需要提前进行流程的计算,以节省时间,举例如下:

    1.第一种,单纯由transforms构成的计算任务,当一个数据处理流程中存在异构计算平台的时候,需要将前一个Spark计算任务的RDD数据向后进行传递,可以采用采用mapPartition的方式,以分区数据为单位进行传递,在这个spark计算任务中,必须要一个操作来触发mapPartition以及其分区操作函数,当然可以用一个简单的count()或者show()操作进行触发。

    2.第二种,需要提前进行流程的计算,尽可能的为流程的后半部分节省时间,当后面的任务触发的时候,可以直接使用前面流程计算好的数据,而不是一个假数据。

 

正文

1.count() / show() 等方式进行触发

    这是最简单的一种方式,但是会引入额外的计算成本,比如count(),而show()的API调用会触发collect函数的调用,而且使用方式上也不够优雅。

2.sparkContext.runjob()方法触发

    runjob()函数,每个action操作的执行方法中都包含一个方法调用,用来触发和提交Spark计算任务,该方法在sparkContext方法中,提供了以下几种调用接口:

其中有一个调用接口是有返回值的,可以返回一些计算过程中的信息,下面是一个简单的包装类,传入一个Dataset,触发其计算任务之后返回新的Dataset:

public class SparkJobSubmiter {
    //静态方法
    public static Dataset<Row> runJob(Dataset<Row> ds){
        RDD<Row> rdd = ds.rdd();
        //记录数据的schema信息,用于恢复
        StructType sche = ds.schema();
        //只能传入RDD
        ds.sparkSession().sparkContext().runJob(rdd, new JobFunc(), ClassTag$.MODULE$.apply( Void.class ));
        
        //恢复schema数据
        return ds.sparkSession().createDataFrame(rdd,sche);
    }
}

//辅助类 可以收集计算过程中的辅助信息
class JobFunc extends AbstractFunction1<Iterator<Row>, Void> implements Serializable {
    
    @Override
    public Void apply(Iterator<Row> iterator) {
    
        //可以添加自己的逻辑操作,监控计算过程
        return null;
    }
}

总结

     手动触发纯transform的计算任务,往往计算结果不重要,而是要在计算过程中执行相关操作,除了transform的非常规操作之外,有时候,还会手动的构造Dataset数据集,Dataset构成为两部分:数据+计算逻辑,我们可以替换计算逻辑或者数据来达到重用的目的。

     这里推荐一个JAVA 代码搜索网址:https://www.codota.com/code  ,一些不常用的API调用都可以在上面找到相关的例子。

    good luck~

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章