根据 Spark Shuffle概述 最后,reduce task (或者说是 Worker 端)是如何找到索引文件这些磁盘小文件位置的呢?
假如 spark.shuffle.memoryFraction 初始有50M ,第一次拉取数据的时候48M 可以放得下,还剩2M 的内存,第二次拉取的时候放不下了不会 OOM ,以后都不会 OOM ,而是直接溢写磁盘。
假如 spark.shuffle.memoryFraction 初始有30M ,第一次拉取的时候都不够了,这个时候会 OOM。
查看官网如下:
Spark中的内存使用主要分为两类:执行和存储。执行内存是指用于在散列、连接、排序和聚合中进行计算的内存,而存储内存是指用于在集群中缓存和传播内部数据的内存。在Spark中,执行和存储共享一个统一的区域M,当不使用执行内存时,存储可以获取所有可用的内存,反之亦然。执行可能会在必要时回收存储,但只能在总存储内存使用低于某个阈值R时才会回收。换句话说,R描述了M中的一个分区,其中缓存的块永远不会被回收。存储可能不会因为实现的复杂性而收回执行。
这种设计确保了几个理想的性能。首先,不使用缓存的应用程序可以使用整个空间执行,避免不必要的磁盘溢出。其次,使用缓存的应用程序可以保留最小存储空间R,其中的数据块不会被删除。最后,这种方法为各种工作负载提供了合理的开箱即用性能,而不需要用户了解如何在内部分配内存。
虽然有两种相关的配置,但典型的用户不需要调整它们,因为默认值适用于大多数工作负载:
- spark.memory.fraction 表示 (JVM heap space - 300MB) (default 0.6) 部分的大小,剩下的40%作为数据集和内部元数据存储空间,以及在记录稀疏和异常大的情况下防止OOM错误。
- spark.memory.storageFraction 表示将R的大小表示为M的一部分(默认值0.5)。R是M中的存储空间,其中缓存的块不会被执行删除。
spark 1.6之前是静态内存管理,1.6之后是统一内存管理。
spark.memory.fraction 在1.6版本占比是0.75,2.*版本是0.6。
2.*版本中以下参数是默认关闭的:
spark.shuffle.memoryFraction
spark.storage.memoryFraction
spark.storage.unrollFraction