這次不扯蛋夜赵,直接開講寇僧。
該問題的本質(zhì)是序列化問題7邪妗!视粮!序列化問題!P诽凇区宇!序列化問題!R楣取!
重要問題說三遍芬首。
把對(duì)象轉(zhuǎn)換為字節(jié)序列的過程稱為對(duì)象的序列化。
把字節(jié)序列恢復(fù)為對(duì)象的過程稱為對(duì)象的反序列化赦政。
序列化和反序列化為的是對(duì)象經(jīng)過傳輸(也可能是通過文件方式)后耀怜,程序還能對(duì)他進(jìn)行還原成對(duì)應(yīng)object。
序列化 詳解 左拐 https://www.cnblogs.com/xdp-gacl/p/3777987.html
那么為什么會(huì)報(bào)上面那個(gè)問題呢掰派?
因?yàn)槟銈鬏數(shù)膶?duì)象沒有序列化左痢,或者序列化錯(cuò)誤。java中序列化? 是?java.io.Serializable;
但是 該序列化方式開銷比較大俊性,如果使用網(wǎng)絡(luò)傳輸大量對(duì)象,那么可能造成帶寬的大量浪費(fèi)纳像。所以spark自己搞了個(gè)序列化方式拯勉。org.apache.spark.serializer.KryoSerializer。該序列化方式好處是開銷小岔帽。
spark 2.0以上版本 默認(rèn)org.apache.spark.serializer.KryoSerializer序列化方式。如果你使用java 序列化那么鐵定跪了犀勒。所以統(tǒng)一spark序列化方式 要不是這? spark成java序列化方式
conf.set("spark.serializer", "org.apache.spark.serializer.JavaSerializer")
要不對(duì)象注冊(cè)成?KryoSerializer序列化方式妥曲。
conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
conf.set("spark.kryo.registrationRequired", "true")
var arrclasses: Array[Class[_]] =Array(classOf[Sub], classOf[DMPUser],
? classOf[SubType], classOf[org.apache.avro.generic.GenericData.Array[_]], classOf[BasicTag]
, classOf[ExtendTag], classOf[org.apache.avro.util.Utf8], classOf[java.util.HashMap[_, _]], classOf[java.util.Map[_, _]]
, classOf[java.util.ArrayList[_]], classOf[java.util.List[_]], classOf[java.lang.CharSequence])
conf.registerKryoClasses(arrclasses)
但是有時(shí) 使用KryoSerializer注冊(cè)也不是很方便檐盟。比如你用avro格式定義的嵌套格式。完了和我上面的例子一樣 需要注冊(cè)一大堆類葵萎。還不一定注冊(cè)全唱凯。那么怎么辦呢磕昼。
通用解決方式:
? 寫代碼 實(shí)現(xiàn) objectToByte? 和 byteToObject 方法节猿。在有傳輸操作地方 將object轉(zhuǎn)換成byte數(shù)組,在接收操作地方再轉(zhuǎn)回來沐批。
對(duì)于初學(xué)各種大數(shù)據(jù)格式的小朋友會(huì)遇到問題蝎亚。比如 avro自動(dòng)生成的類報(bào)上面錯(cuò),無從下手躺彬。主要是 對(duì)avro理解錯(cuò)誤梅惯。avro提供序列化方式,但是使用avro工具生成的類本身沒有序列化O臣酢!缔刹!但是使用avro工具生成的類本身沒有序列化A诱搿!鸟廓!但是使用avro工具生成的類本身沒有序列化!R铡擎浴!。avro提供了序列化類骏融,例如DatumReader链嘀。
如果使用scala編程怀泊,可以使用case class來定義類误趴。case class 默認(rèn)實(shí)現(xiàn)了java 序列化方式。