【Java序列化與反序列化】
Java序列化是指把Java對象轉換為字節序列的過程;而Java反序列化是指把字節序列恢復為Java對象的過程。
序列化使用場景:
1.數據的持久化,通過序列化可以把數據永久地保存到硬盤上(通常存放在文件里)。
2.遠程通信,即在網絡上傳送對象的字節序列。
這篇文章寫的不錯https://blog.csdn.net/wangloveall/article/details/7992448
【Spark序列化與反序列化場景】
在Spark中,主要有三個地方涉及序列化與反序列化:
1.在算子中使用到廣播變量broadcast時,該變量會被序列化后進行網絡傳輸。
2.自定義對象的類型作為RDD的泛型類型時,例如JavaRDD<Student>,所有自定義類型對象,都會進行序列化,所以要求自定義類必須實現Serializable接口。
3.使用可序列化的持久化策略時,例如MEMORY_ONLY_SER,Spark會將RDD中的每個partition都序列化成一個大的字節數組。
【Spark序列化與反序列化機制】
Spark默認使用的是Java的序列化機制,也就是ObjectOutputStream、ObjectInputStream API來進行序列化和反序列化。
Spark也支持使用Kryo序列化庫,Kryo序列化類庫的性能比Java序列化類庫的性能要高很多。據官方介紹,Kryo序列化機制比Java序列化機制性能高10倍左右。
那么,對於上述3種Spark有序列化處理的方法,建議使用Kryo序列化類庫,優化序列化和反序列化的性能。
Spark之所以默認沒有使用Kryo作為序列化類庫,是因為Kryo要求最好要注冊所有需要進行序列化的自定義類型,使用上略微繁瑣,但並不麻煩。
【Spark使用Kryo序列化與反序列化】
例如,Student和School是自定義的2個類,Kryo使用注意點
SparkConf().set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
Scala:
val conf = new SparkConf().setMaster(...).setAppName(...)
conf.registerKryoClasses(Array(classOf[Student], classOf[School]))
val sc = new SparkContext(conf)
Java:
SparkConf conf = new SparkConf().setMaster(...).setAppName(...)
conf.registerKryoClasses(Student.class, School.class)
JavaSparkContext sc = new JavaSparkContext(conf)
此外
1.Spark參數 spark.kryoserializer.buffer.mb=2,默認值為2,是指配置Kryo默認最大能緩存2M的對象,然后再進行序列化。
如果注冊的要序列化的自定義的Class類型,本身特別大,比如包含的屬性過百,會導致要序列化的對象過大。此時,可使用SparkConf.set()方法,設置spark.kryoserializer.buffer.mb參數的值,將其調大來解決。
2.在SparkStreaming2.4.0與Kafka2.1.1集成編碼中遇到過一個問題:開始沒指定序列化,日志中看到有Serialize的報錯,抱着試試看的心態,設置為kryo序列化方式,set("spark.serializer", "org.apache.spark.serializer.KryoSerializer"),問題得以解決。
我的代碼實踐:https://github.com/wwcom614/Spark