我用Java编写了一个spark spark应用程序。它从数据馈送接收器读取股票交易并将它们转换为Tick对象,并使用微量分钟间隔,窗口间隔和10秒的滑动间隔。创建JavaPairDStream<String, Iterable<Tick>>
,其中键是股票代码。
然后使用mapWithState将Tick对象存储在JavaMapWithStateDStream中;使用Ticks作为输入在mapWithState回调函数中执行分析计算。一切正常,直到我修改程序以在mapWithState回调函数中调用Rserve,以便在R中执行其他分析计算。
当我开始调用Rserve时,每隔10个窗口需要很长时间才能处理;这是也写入检查点文件的窗口(我正在使用Hadoop)。每个第10个窗口比前一个第10个窗口需要更长的处理时间(窗口30比窗口20花费的时间长于窗口10)。所有非检查点窗口都在10秒内完成,但检查点窗口最终可能需要几分钟才能完成,而其他窗口则排在后面。
然后我尝试将JavaMapWithStateDStream上的检查点间隔设置为24小时,以便有效地禁用检查点(mapWithStateStream.checkpoint(Durations.minutes(1440)))。我为3服务器集群上的工作人员启用了足够的内存,以便他们能够承受不断增长的内存使用量。
我输出到日志的结果是出乎意料的。以前JavaPairDStream<String, Iterable<Tick>>
填充了5000个密钥,它仍然存在。但是,以前有5000个密钥被传递给mapWithState回调函数;现在只有200个密钥被传递给它,我看到Spark Streaming UI网页中跳过了很多阶段。当我在MS Windows机器上以单进程模式运行时,仍会将5000个密钥传递给mapWithState回调函数。
有没有人知道为什么调用Rserve会导致检查点时间大幅增加,或者为什么在JavaMapWithStateDStream上调用checkpoint(Durations.minutes(1440))会导致spark无法传递{中的大多数元组{1}}到mapWithState回调函数?