在Spark中广播Joda DateTime时出错

时间:2016-03-01 11:15:40

标签: scala apache-spark jodatime

使用Joda Time with Spark时,下面的代码会导致java.lang.NullPointerException

val todayBroadcast = sc.broadcast(new DateTime())
val dataRDD2 = dataRDD.filter(item => {
                                todayBroadcast.value.minusMonths(1).isBefore(item._1)
                              })

另一方面,下面的代码没有问题

    val dataRDD2 = dataRDD.filter(item => {
                                    val today = new DateTime()
                                    today.minusMonths(1).isBefore(item._1)
                                  })

2 个答案:

答案 0 :(得分:4)

据我所知,Joda在Apache Spark提供的默认序列化方面存在一些问题。特别是问题在于Kryo序列化器。

您可以查看this SO帖子。

无论如何,尝试禁用Kryo序列化并使用标准Java序列化程序org.apache.spark.serializer.JavaSerializer。您可以在Spark安装的spark.serializer内找到属性spark-defaults.conf

现在,您应该拥有以下属性:

spark.serializer=org.apache.spark.serializer.KryoSerializer

你必须改为

spark.serializer=org.apache.spark.serializer.JavaSerializer

然后,重新启动Spark安装。如果您正在使用某个特定的发行版(即Cloudera),请使用他们为您提供的管理控制台更改上述属性。

如果您无法使用标准序列化程序,则可以使用其他一些序列化友好格式转换DateTime,例如StringLong(以毫秒为单位)< / p>

告诉我们。

答案 1 :(得分:4)

如果你想继续使用jry日期时间的Kryo序列化,你可以这样做。这使用了https://github.com/magro/kryo-serializers

中已创建的序列化程序

创建一个扩展KryoRegistrator

的类
import com.esotericsoftware.kryo.Kryo
import org.apache.spark.serializer.KryoRegistrator

class MyRegistrator extends KryoRegistrator {

  import de.javakaffee.kryoserializers.jodatime.{JodaDateTimeSerializer, JodaLocalDateSerializer, JodaLocalDateTimeSerializer}
  import org.joda.time.{DateTime, LocalDate, LocalDateTime}

  override def registerClasses(kryo: Kryo) {
    kryo.register(classOf[DateTime], new JodaDateTimeSerializer())
    kryo.register(classOf[LocalDate], new JodaLocalDateSerializer())
    kryo.register(classOf[LocalDateTime], new JodaLocalDateTimeSerializer())
  }
}

然后使用sparkconf

注册该类
set("spark.kryo.registrator", "MyRegistrator")

这将序列化joda日期时间,本地日期正确

查看https://spark.apache.org/docs/0.6.1/tuning.html处的文档 - &gt;数据序列化