spark之kryo序列化
spark之kryo 序列化
1.定义:把对象转换为字节序列的过程称为对象的序列化。 把字节序列恢复为对象的过程称为对象的反序列化。
通俗地说序列化就是把内存(jvm)中一个对象的状态通过网络传输,或者保存到磁盘上,反序列化与之相反。
2.spark中的序列化那么对象以何种形式进行传输性能更好呢?在spark2.0+版本的官方文档中提到:spark默认提供了两个序列化库:Java自身的序列化和Kryo序列化官网的解释是:java序列化灵活,但是速度缓慢。Kryo序列化速度更快且更紧凑,但是支持的类型较少。而且spark现在已经默认RDD在shuffle的时候对简单类型使用了Kryo序列化。
3.如何使用kryo 序列化spark中已经包含了kryo库,使用kryo只需要注册即可。
Spark 中使用 Kryo序列化
步骤
Spark 中使用 Kryo 序列化主要经过两个步骤
1.声明使用 kryo 序列化
2.注册序列化类
1.声明使用 kryo 序列化
可以在程序中指定,例如
val conf = new SparkConfconf .set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
另一种方式,可以在 spark-submit 通过
--conf spark.serializer=org.apache.spark.serializer.KryoSerializer
2.注册序列化类
这里有两种方式
1.传递classes数组
2.在指定类中,通过kyro注册
1.传递classes数组
private[udf] case class User(id: Int, name: String, city: String)
val conf = new SparkConf()
conf
.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
// .set("spark.kryo.registrationRequired", "true")
方法一
.set("spark.kryo.registrator", "com.spark.test.offline.udf.MyKryoRegistrator")
方法二 //注册自定义类交给KryoSerializer序列化处理类进行序列化
.registerKryoClasses(Array(classOf[com.spark.test.offline.udf.User]
//, classOf[scala.collection.mutable.WrappedArray.ofRef[_]]
))
中文切词案例:
import com.huaban.analysis.jieba.{JiebaSegmenter, SegToken}
import com.huaban.analysis.jieba.JiebaSegmenter.SegMode
import org.apache.spark.SparkConf
import org.apache.spark.sql.{DataFrame, SparkSession}
import org.apache.spark.sql.functions._
object JiebaSeg {
def main(args: Array[String]): Unit = {
// 定义结巴分词类的序列化
val conf = new SparkConf()
//注册自定义类交给KryoSerializer序列化处理类进行序列化
.registerKryoClasses(Array(classOf[JiebaSegmenter]))
//设置优化参数
.set("spark.rpc.message.maxSize","800")
// 建立sparkSession,并传入定义好的Conf
val spark = SparkSession
.builder()
.appName("Jieba UDF")
.enableHiveSupport()
.config(conf)
.getOrCreate()
// 定义结巴分词的方法,传入的是DataFrame,输出也是DataFrame多一列seg(分好词的一列)
def jieba_seg(df:DataFrame,colname:String): DataFrame ={
// 定义类的实例化
val segmenter = new JiebaSegmenter()
//使用广播变量进行序列化(广播变量只能读,不能修改,类似分发)
val seg = spark.sparkContext.broadcast(segmenter)
val jieba_udf = udf{(sentence:String)=>
// 通过value获取到一段中文
val segV = seg.value
segV.process(sentence.toString,SegMode.INDEX)
.toArray().map(_.asInstanceOf[SegToken].word)
.filter(_.length>1).mkString(" ")
}
df.withColumn("seg",jieba_udf(col(colname)))
}
val df =spark.sql("select content,label from badou.new_no_seg limit 300")
val df_seg = jieba_seg(df,"content")
df_seg.show()
// saveAsTable 直接存储到对应的hive表
df_seg.write.mode("overwrite").saveAsTable("badou.news_jieba")
}
}