RDD中的函數和屬性傳遞

在spark中,RDD的創建和初始化是在Driver中執行的,而實際操作是在Executor中進行。如果要涉及到傳遞一些方法或者屬性的時候,那麼就要序列化之後才能進行傳遞。下面用兩個例子來進行說明:

  1. 函數的傳遞
    先看代碼:
object SerializableTest {
    def main(args: Array[String]): Unit = {
        val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("SerializableTest")
        val sc = new SparkContext(conf)
        val dataRDD: RDD[String] = sc.makeRDD(List("hadoop", "hive", "spark", "scala"))
        val test = new Test("h")
        val result: RDD[String] = test.test1(dataRDD)
        result.collect().foreach(println)
    }
}
//RDD中的函數傳遞和屬性
class Test(s: String){

    //定義函數,在driver中執行
    def isContain(data: String): Boolean = {
        data.contains(s)
    }
    //傳遞函數,在Executor中執行
    def test1(rdd: RDD[String]): RDD[String] = {
        rdd.filter(isContain)
    }
}

正如上面所說,初始化的工作是在Driver中進行的,所以Test類在初始化的時候就是在Driver中進行的,後面調用test1方法的時候是在Executor中進行的,而test1中調用了isContain方法,這個方法是在Driver進行的,因爲我這裏是在單機上部署的spark,所以要涉及到進程間的通信了,如果在進羣中運行的話,就涉及到網絡的通信。無論是進程間得到通信還是網絡間的通信,一個普通的類是不能傳輸的,所以要把Test類混入序列化的特質才行,如上面代碼沒有混入特質,執行效果就如下面所示:
在這裏插入圖片描述
所以解決方案是:在Test類中混入Serializable特質,class Test(s: String) extends Serializable{}
混入特質後就能成功運行了。

  1. 屬性的傳遞
    再看代碼:
object SerializableTest {
    def main(args: Array[String]): Unit = {
        val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("SerializableTest")
        val sc = new SparkContext(conf)
        val dataRDD: RDD[String] = sc.makeRDD(List("hadoop", "hive", "spark", "scala"))
        val test = new Test("h")
        val result: RDD[String] = test.test2(dataRDD)
        result.collect().foreach(println)
    }
}
//RDD中的函數傳遞和屬性
class Test(s: String) extends Serializable{
    //定義函數,在driver中執行
    def isContain(data: String): Boolean = {
        data.contains(s)
    }
    //傳遞屬性,在Executor中執行
    def test2(rdd: RDD[String]): RDD[String] = {
        rdd.filter(x => x.contains(s))
    }
}

這個和上面的代碼類似,只不過這次傳遞的只是一個屬性s,但是因爲也涉及到進程的通信或者網絡傳輸,所以都要混入序列化特質才能成功運行。

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