调优 Spark 应用程序的内存使用情况和 GC 行为已经在 优化指南 中详细讨论了。强烈推荐您阅读它。在这一章,我们讨论在 Spark Streaming 应用程序 Context 中指定的一些优化参数。
Spark Streaming 应用程序在群集中需要的 Memory(内存) 数量取决于使用的 Transformations(转换)上的类型行为。例如,如果您想要在最近 10 分钟的时候上使用 Window(窗口)函数,那么您的群集应有有足够的 Memory 以保存 10 分钟值的数据在内存中。或者您想要在大量的 keys 中使用 updateStateByKey,那么所需要的内存将会更高。与之相反,如果您想要去做一个简单的 map-filter-store 操作,那么所需的内存将会更少。
在一般情况下,从数据通过 Receiver(接收器)被接收时起使用 StorageLevel.MEMORY_AND_DISK_SER_2 存储,数据在内存中放不下时将拆分到硬盘中去。这样也许降低了 Streaming 应用程序的性能,因此建议为您的 Streaming 应用程序提供足够的内存。它最好去试一试,并且在小范围看看 Memory(内存)使用情况然后估算相应的值。
内存调优的另一个方面是垃圾收集。Streaming 应用程序需要低延迟,JVM 垃圾回收造成的大量暂停是不可取的。
这里有一些能够帮助你调整内存使用情况以及 GC 开销的参数 :
- Persistence Level of DStreams(DStream 的持久化级别): 像前面所提到的 数据序列化 部分,输入的数据和 RDDs 默认持久化为序列化的字节。和反序列化持久性相比,这样减少了内存使用和 GC 开销。启用 Kryo 序列化进一步减少了序列化大小和内存使用。进一步减少内存使用可以用压缩实现(请看 Spark 配置 spark.rdd.compress),付出的是 CPU 时间。
- Clearing old data(清除旧数据): 默认情况下,所有的输入数据和通过 DStream transformation(转换)产生的持久化 RDDs 将被自动的清除。Spark Streaming 决定何时清除基于使用 transformation(转换)的数据。例如,如果你使用一个 10 分钟的 Window(窗口)操作,那么 Spark Streaming 将保存最近 10 分钟的数据,并主动扔掉旧的数据。数据也能够通过设置 streamingContext.remeber 保持更久(例如,交互式查询旧数据)。
- CMS Garbage Collector(CMS 垃圾回收器): 使用并发的 mark-sweep GC 是强烈推荐的用于保持 GC 相关的暂停更低。即使知道并发的 GC 降低了整个系统处理的吞吐量。仍然建议使用,以获得更一致的批处理时间。确定你在 Driver(在 spark-submit 中使用 --driver-java-options)和 Executor(使用 Spark 配置 spark.executor.extraJavaOptions)上设置的 CMS GC。
- Other tips(其它建议): 为了进一步降低 GC 开销,这里有些更多的建议可以尝试。
- 持久化 RDDs 使用 OFF_HEAP 存储界别。更多详情请看 Spark 编程指南
- 使用更多的 Executor 和更小的 heap size(堆大小)。这将在每个 JVM heap 内降低 GC 压力。