我正在使用Spark Streaming构建一个程序,它对输入数据执行一些线性回归,预测输出数据并打印预测。
我还希望不仅在传入数据上训练模型,而且在最后的xxx数据点上训练我的模型,并且我想为该任务使用Sparks状态计算功能。我的状态保存了一个数据列表,并且在时机成熟时,使用所有数据来训练模型并预测一组新的值。
使用spark-submit将应用程序发送到在mesos群集上运行的spark-dispatcher,该spark也会为应用程序设置主URL。这似乎是你在下面看到的一些问题的根源。
Sparks MLlib算法(LinearRegressionWithSGD)仅接受RDD作为输入。这意味着我必须并行化我在我的状态下保存的数据,例如使用像(sc是火花上下文)这样的东西:
val parallelizedData = sc.parallelize(trainingData)
但是,这会产生一些问题:
我无法为我的状态提供spark上下文,因为它不可序列化,并且显然状态会被发送给所有执行者(我已经尝试过了,我得到了一个NotSerializableException)
我试图定义一个包含spark上下文的对象,并直接在类中使用它,这个想法是一个对象是一个单例,并在函数需要时被复制到spark执行器:
object Spark {
lazy val config = new SparkConf()
lazy val context = new SparkContext
}
// Then in my state mapping fuction:
val parallelizedData = Spark.context.parallelize(trainingData)
在这个版本中,执行程序尝试创建一个新的spark上下文但是因为主URL是通过spark-submit给出的并且没有硬编码,所以它不起作用,我收到错误“你必须提供一个主URL” 。这似乎是错误的,因为显然我不想(也不能)创建一个新的上下文,但是使用已经存在的旧上下文,并且在我尝试训练模型之前很久就在我的主程序中使用。
我还尝试将上面Spark对象中的主URL设置为调度程序的主URL,但这也不起作用。将其硬编码为“本地[N]”可以正常工作,但是应用程序不是并行化的,而是仅在驱动程序上执行。
有没有人有过火花状态计算的经验?网上似乎只有很少的文档,其中大部分都不适用于我的情况。如何将上下文发送到州?或者,如何强制在驱动程序上执行状态,以便它可以访问状态?
或者我可以创建一个仅驻留在worker上的RDD并将其发送回驱动程序,驱动程序又会聚合结果并创建一个可用于训练的新RDD吗?