Spark 序列化问题
在Spark应用开发中,很容易出现如下报错:
org.apache.spark.SparkException: Task not serializable
  at org.apache.spark.util.ClosureCleaner$.ensureSerializable(ClosureCleaner.scala:304)
  at org.apache.spark.util.ClosureCleaner$.org$apache$spark$util$ClosureCleaner$$clean(ClosureCleaner.scala:294)
  at org.apache.spark.util.ClosureCleaner$.clean(ClosureCleaner.scala:122)
  at org.apache.spark.SparkContext.clean(SparkContext.scala:2058)
  ...
Caused by: java.io.NotSerializableException该报错意思是用户代码的transformation操作中包含不可序列化的对象引用。
本文主要从以下三个方面解释Spark 应用中序列化问题 。 
1、Java序列化含义? 
2、Spark代码为什么需要序列化? 
3、如何解决Spark序列化问题?
1、Java序列化含义?
Spark是基于JVM运行的进行,其序列化必然遵守Java的序列化规则。
序列化就是指将一个对象转化为二进制的byte流(注意,不是bit流),然后以文件的方式进行保存或通过网络传输,等待被反序列化读取出来。序列化常被用于数据存取和通信过程中。
对于java应用实现序列化一般方法:
- class实现序列化操作是让class 实现Serializable接口,但实现该接口不保证该class一定可以序列化,因为序列化必须保证该class引用的所有属性可以序列化。 
- 这里需要明白,static和transient修饰的变量不会被序列化,这也是解决序列化问题的方法之一,让不能序列化的引用用static和transient来修饰。(static修饰的是类的状态,而不是对象状态,所以不存在序列化问题。transient修饰的变量,是不会被序列化到文件中,在被反序列化后,transient变量的值被设为初始值,如int是0,对象是null) 
- 此外还可以实现readObject()方法和writeObject()方法来自定义实现序列化。(具体用例见参考链接) 
2、Spark的transformation操作为什么需要序列化?
Spark是分布式执行引擎,其核心抽象是弹性分布式数据集RDD,其代表了分布在不同节点的数据。Spark的计算是在executor上分布式执行的,故用户开发的关于RDD的map,flatMap,reduceByKey等transformation 操作(闭包)有如下执行过程: 
1. 代码中对象在driver本地序列化 
2. 对象序列化后传输到远程executor节点 
3. 远程executor节点反序列化对象 
4. 最终远程节点执行 
故对象在执行中需要序列化通过网络传输,则必须经过序列化过程。
3、如何解决Spark序列化问题?
如果出现NotSerializableException报错,可以在spark-default.xml文件中加入如下参数来开启SerializationDebugger功能类,从而可以在日志中打印出序列化出问题的类和属性信息。
spark.executor.extraJavaOptions  -Dsun.io.serialization.extendedDebugInfo=true
spark.driver.extraJavaOption -Dsun.io.serialization.extendedDebugInfo=true对于scala语言开发,解决序列化问题主要如下几点:
- 在Object中声明对象 (每个class对应有一个Object)
- 如果在闭包中使用SparkContext或者SqlContext,建议使用SparkContext.get() and SQLContext.getActiveOrCreate()
- 使用static或transient修饰不可序列化的属性从而避免序列化。 
 注:scala语言中,class的Object
对于java语言开发,对于不可序列化对象,如果本身不需要存储或传输,则可使用static或trarnsient修饰;如果需要存储传输,则实现writeObject()/readObject()使用自定义序列化方法。
此外注意
对于Spark Streaming作业,注意哪些操作在driver,哪些操作在executor。因为在driver端(foreachRDD)实例化的对象,很可能不能在foreach中运行,因为对象不能从driver序列化传递到executor端(有些对象有TCP链接,一定不可以序列化)。所以这里一般在foreachPartitions或foreach算子中来实例化对象,这样对象在executor端实例化,没有从driver传输到executor的过程。
dstream.foreachRDD { rdd =>
  val where1 = "on the driver"
    rdd.foreach { record =>
      val where2 = "on different executors"
    }
  }
}参考资料: 
Avoid NotSerializable Error in Spark Job 
spark not serializable problem 
Spark Streaming / Tips on Running Streaming Apps inside Databricks 
Java 序列化的高级认识 
什么是writeObject 和readObject?可定制的序列化过程
Spark 序列化问题的更多相关文章
- spark序列化及MapOutputTracker解析
		本文主要打算对spark内部的序列化机制以及在shuffle map中起衔接作用的MapOutputTracker做一下剖析.主要涉及具体实现原理以及宏观设计的一些思路. 1,spark序列化 任何一 ... 
- spark系列-4、spark序列化方案、GC对spark性能的影响
		一.spark的序列化 1.1.官网解释 http://spark.apache.org/docs/2.1.1/tuning.html#data-serialization 序列化在任何分布式应用程序 ... 
- 在Spark中使用Kryo序列化
		spark序列化 对于优化<网络性能>极为重要,将RDD以序列化格式来保存减少内存占用. spark.serializer=org.apache.spark.serializer.Jav ... 
- 【Spark调优】Kryo序列化
		[Java序列化与反序列化] Java序列化是指把Java对象转换为字节序列的过程:而Java反序列化是指把字节序列恢复为Java对象的过程.序列化使用场景:1.数据的持久化,通过序列化可以把数据永久 ... 
- Spark性能优化(1)——序列化、内存、并行度、数据存储格式、Shuffle
		序列化 背景: 在以下过程中,需要对数据进行序列化: shuffling data时需要通过网络传输数据 RDD序列化到磁盘时 性能优化点: Spark默认的序列化类型是Java序列化.Java序列化 ... 
- Hadoop的Writerable在Spark无法序列化的问题
		Spark序列化这块网上讲的比较少,自己还没来得及看这块代码,今天编程的时候遇到一个Hadoop的Writerable实现在Spark无法序列化的问题.我的代码如下: object EntryApp ... 
- 浅谈Spark Kryo serialization
		原创文章,转载请注明: 转载自http://www.cnblogs.com/tovin/p/3833985.html 最近在使用spark开发过程中发现当数据量很大时,如果cache数据将消耗很多的内 ... 
- Spark调优与调试
		1.使用SparkConf配置Spark (1)在java中使用SparkConf创建一个应用: SparkConf conf =;i++){ javaBean bean =new javaBean( ... 
- Spark生态以及原理
		spark 生态及运行原理 Spark 特点 运行速度快 => Spark拥有DAG执行引擎,支持在内存中对数据进行迭代计算.官方提供的数据表明,如果数据由磁盘读取,速度是Hadoop MapR ... 
随机推荐
- R基础-适合于纯小白
			#说明 文中‘test’均为模拟名称,原始编码为GKB方式###1.R语言介绍#### 偏统计 ###2.Rstudio和R的基本操作#### #2.1查看R语言自带的数据集#### data() # ... 
- 如何批量下载bing的背景图片?
			工具准备 wget(点击下载) 批处理命令(点击下载) 网友提供的接口:http://area.sinaapp.com/bingImg?daysAgo=1(1代表天数) 实现步骤 1.打开记事本,并将 ... 
- ROS C++ 规范概要
			一.动机 代码一致才能可读.联调.高效率.高复用.可移植性. 二.命名方式 CamelCased camelCased under_scored ALL_CAPITALS 2.1 Package命名方 ... 
- iOS之限制TextField的输入长度
			网上有很多限制textField输入长度方法,但是我觉得都不是很完美,准确来说可以说是不符合实际开发的要求,因此在这里整理一下textField限制输入长度的方法.我所采用的并不是监听方法而是最不同的 ... 
- Eclipse中按CTRL键点击类不能进入
			是因为Eclipse或项目没有关联jdk,首先看window->preferences->java->Installed JREs,看是不是关联的你所安装的jdk,有的是关联的JRE ... 
- Java常用类归纳(Object、System、Properties、包装类和工具类等等)
			Object类 Object 是类层次结构的根类.每个类都使用 Object 作为超类,所有对象(包括数组)都实现这个类的方法.了解Object的方法是很有必要的. protected Object ... 
- 1004. Counting  Leaves(30)—PAT 甲级
			A family hierarchy is usually presented by a pedigree tree. Your job is to count those family member ... 
- Z字形编排问题详解(C++)
			Z字形编排问题详解(C++): 问题描述:给定一个矩阵matrix,输出矩阵matrix进行Z字形编排后的内容. 原矩阵: 输出形式: 算法分析与详细解答: 要解决这样一个问题,可能一开始无从下手,但 ... 
- CentOS7.6离线安装JDK1.8
			卸载CentOS自带的openJDK: 查看openJDK命令:rpm -qa|grep java 结果: java-1.8.0-openjdk-headless-1.8.0.181-7.b13.el ... 
- 局域网内python socket实现windows与linux间简单的消息传送
			有个需求,就是在windows上看见一篇介绍linux相关的文章,想在局域网内的另外一台linux电脑上尝试一下, 于是就需要把该网页链接发送给linux,不想一点一点敲链接,又苦于没有找到其它好的方 ... 
