49

我正在运行一个有 2 个工作人员的 Spark 流应用程序。应用程序具有连接和联合操作。

所有批次都成功完成,但注意到 shuffle 溢出指标与输入数据大小或输出数据大小不一致(溢出内存超过 20 次)。

请在下图中找到火花阶段的详细信息: 在此处输入图像描述

对此进行了研究,发现

当没有足够的内存用于 shuffle 数据时,就会发生 Shuffle 溢出。

Shuffle spill (memory)- 溢出时内存中数据的反序列化形式的大小

shuffle spill (disk)- 溢出后磁盘上数据的序列化形式的大小

由于反序列化数据比序列化数据占用更多空间。所以,Shuffle 溢出(内存)更多。

注意到这种溢出内存大小对于大输入数据来说非常大

我的查询是:

这种溢出是否会显着影响性能?

如何优化这种内存和磁盘溢出?

是否有任何 Spark Properties 可以减少/控制这种巨大的溢出?

4

2 回答 2

57

学习调整 Spark 的性能需要大量的调查和学习。有一些很好的资源,包括这个视频。Spark 1.4 在界面中有一些更好的诊断和可视化可以帮助你。

总之,当阶段结束时 RDD 分区的大小超过 shuffle 缓冲区可用的内存量时,就会发生溢出。

你可以:

  1. 手动执行repartition()您的前一阶段,以便您从输入中获得更小的分区。
  2. 通过增加执行器进程中的内存来增加 shuffle 缓冲区 ( spark.executor.memory)
  3. spark.shuffle.memoryFraction通过从默认值 0.2增加分配给它的执行程序内存的比例 ( ) 来增加 shuffle 缓冲区。你需要回馈spark.storage.memoryFraction
  4. 通过降低工作线程 ( SPARK_WORKER_CORES) 与执行程序内存的比率来增加每个线程的 shuffle 缓冲区

如果有专家在听,我很想了解更多关于 memoryFraction 设置如何相互作用及其合理范围的信息。

于 2015-06-12T11:24:54.637 回答
5

要添加到上述答案,您还可以考虑将分区的默认数量(spark.sql.shuffle.partitions)从 200(发生随机播放时)增加到将导致分区大小接近 hdfs 块大小(即 128mb 到 256mb)

如果您的数据有偏差,请尝试使用诸如加盐键之类的技巧来增加并行度。

阅读本文以了解 spark 内存管理:

https://0x0fff.com/spark-memory-management/

https://www.tutorialdocs.com/article/spark-memory-management.html

于 2019-10-24T19:21:28.627 回答