Apache spark 检查点设置时foreachRDD()中使用的对象的序列化
根据我所阅读的文件和资料,Spark Streaming的foreachRDD(someFunction)将只在驱动程序进程中执行someFunction本身,尽管如果在RDD上执行操作,那么它们将在RDD所在的执行器上执行 所有这些对我来说都很有用,尽管我注意到,如果我打开检查点,那么spark似乎正在尝试序列化foreachRDD(someFunction)中的所有内容并发送到某个地方——这对我来说是一个问题,因为使用的一个对象是不可序列化的(即schemaRegistryClient)。我试过Kryo连载器,但也没有成功 如果我关闭检查点,序列化问题就会消失 有没有办法让Spark在继续使用检查点的同时不序列化foreachRDD(someFunc)中使用的内容Apache spark 检查点设置时foreachRDD()中使用的对象的序列化,apache-spark,spark-streaming,rdd,avro,kryo,Apache Spark,Spark Streaming,Rdd,Avro,Kryo,根据我所阅读的文件和资料,Spark Streaming的foreachRDD(someFunction)将只在驱动程序进程中执行someFunction本身,尽管如果在RDD上执行操作,那么它们将在RDD所在的执行器上执行 所有这些对我来说都很有用,尽管我注意到,如果我打开检查点,那么spark似乎正在尝试序列化foreachRDD(someFunction)中的所有内容并发送到某个地方——这对我来说是一个问题,因为使用的一个对象是不可序列化的(即schemaRegistryClient)。我
非常感谢。这里有几件事很重要:
对象,该属性将在需要时加载到工作节点中:
object RegisteryWrapper {
@transient lazy val schemaClient: SchemaRegisteryClient = new SchemaRegisteryClient()
}
当您需要在foreachRDD中使用它时:
someStream.foreachRDD {
rdd => rdd.foreachPartition { iterator =>
val schemaClient = RegisteryWrapper.schemaClient
iterator.foreach(schemaClient.send(_))
}
}
问题可能在于检查点数据,如果您更改了代码中的任何内容,则需要删除旧的检查点元数据。非常感谢Yuval,您的建议很有效。接下来的一个问题是,关于这句话“有一个惰性瞬态属性,它将在需要时加载到工作节点内部”——根据这个[link](),它表示“Scala为根本不应该序列化的字段提供了@transient注释”——因此,如果工作节点上需要schemaRegistryClient,如果没有序列化,它怎么可能被发送给工人(或者除了它的出生地司机以外的任何地方)?@howard它没有发送给工人。但是,别忘了工人有操作所需的所有罐子。这意味着,如果需要一个实例,工作者将加载相关类并创建一个实例。根本不需要序列化。我明白了,因为schemaRegistry被定义为一个对象变量,所以它在对象定义中,因此工作人员可以仅从jar本身构造它。类似的规则也适用于检查点,它不是序列化的,也不保存在HDFS上,但驱动程序也有jar,可以从对象定义构建它-因此将其作为对象定义、@transient注释和惰性前缀都是此模式工作所必需的。再次感谢@Yuval@YuvalItzchakov OP询问如何序列化对象。是否可以在foreachRDD
中创建一个不可序列化的对象,或者Spark在所有foreach*
函数中强制执行序列化规则?@CᴴᴀZ如果在foreachRDD
函数中分配对象,则Spark必须确保其可序列化,因为它必须将其发送到RDD的每个分区(当然,这假设您正在调用RDD.foreach
或RDD.map
)。另一方面,在rdd.foreachPartition
中,如果在那里分配,则分配会在每个分区本地进行,因此不需要序列化。