有人可以解释一下Spark Streaming如何执行window()操作?从Spark 1.6.1文档中,似乎窗口批次会自动缓存在内存中,但是在Web UI中,似乎已经在先前批次中执行的操作再次执行。为方便起见,我附上了正在运行的应用程序的屏幕截图:
通过查看Web UI,似乎缓存了flatMapValues()RDD(绿点 - 这是我在DStream上调用window()之前执行的最后一个操作),但同时,它似乎也是在以前的批次中导致flatMapValues()的所有转换都会再次执行。如果是这种情况,window()操作可能会导致巨大的性能损失,特别是如果窗口持续时间为1或2小时(正如我对我的应用程序所期望的那样)。你认为那时检查点DStream会有帮助吗?考虑到预期的幻灯片窗口大约是5分钟。
希望有人能澄清这一点。
我添加了一个代码段。 Stream1和Stream2是从HDFS读取的数据馈送
JavaPairDStream<String, String> stream1 = cdr_orig.mapToPair(parserFunc)
.flatMapValues(new Function<String, Iterable<String>>() {
@Override
public Iterable<String> call(String s) {
return Arrays.asList(s.split(","));
}
}).window(Durations.seconds(WINDOW_DURATION), Durations.seconds(SLIDE_DURATION));
JavaPairDStream<String, String> join = stream2.join(stream1);
这两个流由另一个系统定期生成。这些流是异步的,这意味着在时间t的stream2中的记录在时间t'&lt; = t时出现在stream1中。我正在使用window()来缓存stream1记录1-2个小时,但如果在每个新批次上执行过去批次的stream1上的操作,这可能效率很低。
答案 0 :(得分:1)
首先是yes window()通过调用persist来缓存dStream。通过缓存在这里我的意思是数据保存在内存中。默认存储级别为StorageLevel.MEMORY_ONLY_SER,即
将RDD存储为序列化Java对象(每个分区一个字节数组)。 这通常比反序列化的对象更节省空间, 特别是在使用快速串行器时,但CPU占用更多 读取。
什么窗口转换会返回一个新的DStream,其中每个RDD包含在此DStream上的滑动时间窗口中看到的所有元素。在内部,它创建了一个WindowedDStream对象,该对象调用persist()来缓存DStream,并且根据Spark API文档“默认情况下它会保持在父级别,因为这些RDD显然会被重用。”
因此,您不能依赖Window来缓存DStreams。如果你想减少转换,你应该在DStreams之前和其他转换之前调用persist()。
在您的情况下,尝试调用persist,如下所示:
cdr_orig.persist(StorageLevel.MEMORY_AND_DISK);
在执行mapToPair转换之前。你会看到一个更紧凑的DAG将在顶部形成绿点。