【发布时间】:2017-06-21 00:05:27
【问题描述】:
我知道对此有很多问题,但我无法找到系统的解释来说明究竟什么需要可序列化(以及何时序列化)......以及如何验证此要求。
考虑一下:
class Baz
trait Bar { val baz = new Baz; def bar(i: Int) = baz }
case object Foo extends Bar { def foo = sc.parallelize(1 to 1).map(bar).collect }
Foo.foo
这有效,并返回Array(null)
这对任何人都有意义吗???
如果我将 val 更改为 lazy val,那么它停止工作,并抛出 NotSerializableException,这是有道理的 - 它在远程端初始化 baz,然后无法把它退回。
但是为什么在第一种情况下它会愉快地用null替换它???
如果我写它,几乎是我能想到的任何其他方式 - 例如,将 bar 定义从 trait 移动到对象,或者将 bar 调用替换为 _ => baz - 它也停止工作,并抱怨Task is not serializable.
返回一个在 trait 中定义的 val 的方法是什么,这使得它只是将其写为 null 而不是?有什么想法吗?
更新
上述行为发生在带有 spark 2.1.1 的 scala 2.11 上。
Scala 2.10 (spark 1.6.0) 确实抛出异常,抱怨Baz 不可序列化......所以,这似乎是一种回归。
另外我注意到在 spark 1.6.0 上,这样的东西可以正常工作:
object Foo { def foo = sc.parallelize(1 to 1).map(bar).collect; def bar(i: Int) = i+1 }
Foo.foo
但在 spark 2.1.1 上,它抱怨 Foo 不可序列化。这是为什么?
显然,序列化 lambda 还希望序列化 Foo,这 有点 是有道理的......除了它 确实 在 1.6.0 中以某种方式工作,即使我制作 labda实际引用Foo中的其他东西:
object Foo {
var stuff = 10
def foo = sc.parallelize(1 to 1).map(bar).collect
def bar(i: Int) = { stuff += 1; i+1 }
}
Foo.foo
Foo.stuff
这在 1.6.0 中可以正常工作,但在 2.1.1 中不行。
所以,这里的一个问题是它在 1.6.0 中实际上是如何工作的?我的意思是,Foo 不可序列化,它如何知道另一端的stuff 的值?
另一个明显的问题是 - 为什么它在 2.1.1 中停止工作? 1.6.0 的行为是否存在微妙的问题,我们不应该依赖它吗? 还是只是 2.1.1 的一个 bug?
【问题讨论】:
标签: scala apache-spark serialization