为什么将 spark 中的参数提取到局部变量被认为更安全?

Why extracting an argument in spark to local variable is considered safer?

我在这本书上看到这个例子《学习Spark:闪电般快速的大数据分析》:

class SearchFunctions(val query: String) {
 // more methods here
 def getMatchesNoReference(rdd: RDD[String]): RDD[String] = {
 // Safe: extract just the field we need into a local variable
 val query_ = this.query
 rdd.map(x => x.split(query_))
 }
}

我的问题是 - 评论说: 安全:仅将我们需要的字段提取到局部变量中

为什么提取到局部变量比使用字段(定义为 val)本身更安全?

因为当您仅提取时 query_ 必须序列化并发送给工作人员。

如果您不提取,将发送 SearchFunctions 的完整实例。

Passing Functions in Spark 真的很有帮助,可以回答您的问题。

想法是您只希望将查询传达给需要它的工作人员,而不是整个对象(class)。

如果您没有那样做(如果您使用 map() 中的字段而不是局部变量),那么:

...sending the object that contains that class along with the method. In a similar way, accessing fields of the outer object will reference the whole object


请注意,这也更安全,不仅效率更高,因为它最大限度地减少了内存使用

你看,当处理非常大的数据时,你的作业将面临内存限制,如果超过它们,它将被资源管理器(例如 YARN)杀死,所以我们要确保我们使用尽可能少的内存,以确保我们的工作能够完成而不是失败!

而且,对象越大,通信开销越大。 TCP 连接可能会被 peer 重置,当通信量太大时,这将调用不必要的开销,我们希望避免这种情况,因为通信不良也是作业失败的原因。

因为其他答案没有提到它:它更安全的另一个原因是因为 class 您引用的 fields/methods 可能无法序列化。由于 Java 不允许在编译时检查它,您将遇到运行时故障。 Whosebug上这类问题的例子非常多:我找到的前几个是Task not serializable: java.io.NotSerializableException when calling function outside closure only on classes not objects, , Enriching SparkContext without incurring in serialization issues, Spark serialization error。搜索 spark NotSerializableException 应该会给你更多,当然不仅仅是在 Stack Overflow 上。

或者它现在可能是可序列化的,但显然不相关的更改(例如添加您的 lambda 不使用的字段)可能会破坏您的代码,使其不可序列化或显着降低您的性能。