美文网首页
Spark not Serializable:为什么对象写在ma

Spark not Serializable:为什么对象写在ma

作者: 朝朝Mumu | 来源:发表于2021-06-13 15:07 被阅读0次

    问题背景

    在用scala编写spark应用程序的时候,如果在executor中要用到一些公参变量、配置或自定义样例类,如case class等等,直接依照常规方法定义局部变量使用会报错“xxx 不可序列化(Task not serializable: java.io.NotSerializableException)”,以及对象不可序列化(object not serializable),这时可以通过把报错变量提升到main方法外或继承Serializable来解决,but why?

    这个问题涉及java静态关键字和spark闭包的知识,研究整理如下,欢迎一起讨论。

    Java的static关键字

    在类中,变量的前面有修饰符static的称为静态变量(类变量),方法的前面有修饰符static的称为静态方法(类方法)。
    静态方法和静态变量属于某一个类,而不属于类的对象。静态变量和静态方法在类被加载的时候就分配了内存空间 。

    Scala的object与class

    • object
      在Scala中没有静态修饰符,在object下的成员全部都是静态的,可以理解为Scala把java类中的static集中放到了object对象中,定义在object中的所有成员变量和方法默认都是 static,但定义在main方法里的则仅仅是一个普通的局部变量。

    • class
      在scala中,类名可以和对象名相同,该对象称为该类的伴生对象。类只会被编译加载,不能直接被执行。类和主构造器在一起被申明,主构造器会执行类定义中的所有语句。伴生对象在第一次使用的时候会调用构造器。

    Spark的闭包

    RDD相关操作都需要传入自定义闭包函数(closure),如果这个函数需要访问外部变量,那么需要遵循一定的规则,否则会抛出运行时异常。闭包函数传入到节点时,需要经过下面的步骤:

    • driver通过反射,运行时找到闭包访问的所有变量,并封装成一个对象,然后序列化该对象(serialized on the driver node)
    • 将序列化后的对象通过网络传输到worker节点(shipped to the appropriate nodes in the cluster)
    • worker节点反序列化闭包对象(deserialized)
    • worker节点执行闭包函数(and finally executed on the nodes)
      总之,就是要通过网络传递函数然后执行,所以被传递的变量必须可序列化,否则传递失败。本地执行时,仍然会执行上面4步。

    因此解决不可序列化问题无非以下两种方法:

    1. 避免序列化:
      不在map、filter等闭包内部直接引用某类(通常是当前类)的成员函数或成员变量,可以定义在map、filter等操作内部((或使用lazy声明))或者定义在object对象中(也就是main方法外部)。
    2. 序列化它:
      对相应的引用某类的成员函数或变量做好序列化处理,主要是继承序列化类(with Serializable)。

    加上了lazy,相当于不对这个值进行序列化了,而是把这个隐式转换对象整个打包发送到worker上,然后用的时候才去加载。
    还有,对于可以不需要序列化的成员变量可使用“@transient ”标注,被transient关键字修饰的变量不再能被序列化(慎用),一个静态变量不管是否被transient修饰,均不能被序列化。

    小结

    静态成员不属于对象,属于类,不能被序列化,还有瞬态的变量也不能被序列化 。
    Java对象中static,transient修饰的成员不能被序列化。
    static变量保存在全局数据区,在对象未实例化时就已经生成,属于类的状态。
    Scala object中定义的变量默认被static修饰,所以定义在main方法外可以不被序列化(spark闭包)。
    最后,节点容器中,在本地的JVM中实例化静态变量,对象加载类时直接使用它,从而绕过了网络传输那一步,最终避免了序列化错误。

    相关文章

      网友评论

          本文标题:Spark not Serializable:为什么对象写在ma

          本文链接:https://www.haomeiwen.com/subject/vioweltx.html