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~

 

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