调优是一个动态的过程,需要根据业务数据的特性和硬件设备来综合调优。
Spark的配置参数官网链接
属性参数 | 默认值 | 含义 |
---|---|---|
spark.reducer.maxSizeInFlight #F44336 | 48MB | 由于每个输出都需要创建一个缓冲区来接收它,因此每个reduce任务的内存开销都是固定的,所以要保持较小的内存,除非您有大量的内存 |
spark.reducer.maxReqsInFlight | Int.MaxValue | 这种配置限制了在任何给定点获取块的远程请求的数量。当集群中的主机数量增加时,可能会导致到一个或多个节点的大量入站连接,从而导致工作人员在负载下失败。通过允许它限制获取请求的数量,可以缓解这种情况。 |
spark.reducer.maxBlocksInFlightPerAddress | Int.MaxValue | 这种配置限制了从给定主机端口为每个reduce任务获取的远程块的数量。当一次获取或同时从给定地址请求大量块时,可能会导致服务执行器或节点管理器崩溃。当启用外部洗牌时,这对于减少节点管理器上的负载特别有用。您可以通过将其设置为一个较低的值来缓解这个问题。 |
spark.maxRemoteBlockSizeFetchToMem | Long.MaxValue | 当块的大小(以字节为单位)超过这个阈值时,远程块将被取到磁盘。这是为了避免占用太多内存的巨大请求。默认情况下,这只对块大于 2GB启用,因为这些块不能直接获取到内存中,无论有什么资源可用。但是它可以被降低到一个更低的值。为了避免在较小的块上使用太多的内存。注意,此配置将同时影响shuffle获取和块管理器远程块获取。对于启用外部洗牌服务的用户,此功能只能在外部洗牌服务比Spark 2.2更新时使用。 |
spark.shuffle.compress #F44336 | true | 是否压缩map输出文件。压缩将使用 spark.io.compression.codec。 |
spark.shuffle.file.buffer #F44336 | 32KB | 每个shuffle文件输出流的内存缓冲区大小。这些缓冲区减少了在创建中间shuffle文件时进行的磁盘搜索和系统调用的次数。 |
spark.shuffle.io.maxRetries #9C27B0 | 3 | (仅限Netty)如果将此设置为非零值,在IO相关异常导致获取数据失败,将自动重试。重试将有助于保障长时间GC停顿或瞬时网络连接问题情况下Shuffle的稳定性 |
spark.shuffle.io.numConnectionsPerPeer | 1 | (仅限Netty)重新使用主机之间的连接,以减少大型群集的连接建立。对于具有许多硬盘和少量主机的集群,这可能导致并发性不足以使所有磁盘饱和,因此用户可能会考虑增加此值。 |
spark.shuffle.io.preferDirectBufs | ture | (仅限Netty)非堆缓冲区用于在Shuffle和缓存块传输过程中减少垃圾回收。对于非堆内存严格限制的环境,用户可能希望将其关闭,以强制Netty的所有分配都在堆上 |
spark.shuffle.io.retryWait #9C27B0 | 5S | (仅限Netty)在重试提取之间等待多长时间。默认情况下,重试导致的最大延迟为15秒,计算方式为maxRetries * retryWait。 |
spark.shuffle.service.enabled #FF9800 | false | 启用外部Shuffle服务。此服务保留由Executor写入的Shuffle文件,以便Executors可以安全地删除。如果spark.dynamicAllocation.enabled为“true”,则必须启用此选项 。必须设置外部Shuffle服务才能启用它。 |
spark.shuffle.service.port | 7337 | 外部Shuffle服务运行的端口 |
spark.shuffle.service.index.cache.size #F44336 | 100M | 缓存Shuffle服务的索引文件的内存大小 |
spark.shuffle.maxChunksBeingTransferred | Long.MAX_VALUE | 允许在Shuffle服务上同时传输的最大块数。请注意,当达到最大数量时,将关闭新的传入连接。客户端将根据shuffle重试配置重试(请参阅spark.shuffle.io.maxRetries和 spark.shuffle.io.retryWait),如果达到这些限制,任务将因提取失败而失败。 |
spark.shuffle.sort.bypassMergeThreshold #F44336 | 200 | (高级)在基于排序的shuffle manager中,如果没有map端聚合,并且最多有这么多reduce分区,则避免合并排序数据 |
spark.shuffle.spill.compress #F44336 | true | 是否压缩在Shuffle期间溢出的数据。压缩将使用 spark.io.compression.codec。 |
spark.shuffle.accurateBlockThreshold | 100 * 1024 * 1024 | 以字节为单位的阈值,高于该阈值可准确记录HighlyCompressedMapStatus中Shuffle块的大小。这有助于通过避免在获取shuffle块时低估shuffle块大小来防止OOM。 |
spark.shuffle.registration.timeout | 5000 | 超时(以毫秒为单位),用于注册到外部洗牌服务 |
spark.shuffle.registration.maxAttempts | 3 | 当我们未能注册到外部shuffle服务时,我们将重试maxAttempts次。 |
压缩算法的比较
https://blog.csdn.net/zhuiqiuuuu/article/details/78130382
Spark Shuffle中JVM内存使用及配置内幕详情
spark.memory.useLegacyMode此参数控制是使用统一内存管理还是使用静态内存的管理,默认是false。
采用静态内存管理的策略时,Spark会定义一个安全空间,在默认情况下只会使用Java堆上的90%作为安全空间,在单个Executor的角度来讲,就是Heap Size x 90% (如果你的内存空间Heap非常大的话,可以尝试调高为95%),在安全空间中也会划分三个不同的空间:一个是Storage空间、一个是Unroll空间和一个是Shuffle空间。
安全空间():计算公式 spark.executor.memory x spark.storage.safetyFraction 。 也就是Heap Size x 90% 。
缓存空间(Storage) : 计算公式是 spark.executor.memory x spark.storage.safetyFraction x spark.storage.memoryFraction 。也就是Heap Size x 90% x 60% ; Heap Size x 54% 。一个应用程序可以缓存多少数据是由 safetyFraction 和 memoryFraction 这两个参数共同决定的。
Unroll空间:计算公式是spark.executor.memory x spark.storage.safetyFraction x spark.storage.memoryFraction x spark.storage.unrollFraction 。 也就是Heap Size x 90% x 60% x 20%;Heap Size x 10.8% 。你可能把数据序列化后的数据放在内存中,当你使用数据时,你需要把序列化的数据进行反序列化。
对cache缓存数据的影响是由于Unroll 是一个优先级较高的操作,进行Unroll操作的时候会占用cache的空间,而且又可以挤掉缓存在内存中的数据(如果该数据的缓存级别是MEMORY_ONLY 的话,数据可能会丢失)。
Shuffle空间 : 计算公式是 spark.executor.memory x spark.shuffle.memoryFraction x spark.shuffle.safteyFraction 。 在Shuffle空间中也会默认80%的安全空间比例,所以应该是Heap Size x 20% x 80%;Heap Size x 16% 。 从内存的角度讲,你需要从远程抓取数据,抓取数据是一个Shuffle的过程,比如说你需要对数据进行排序,显现在这个过程中需要内存空间。
Spark在使用静态内存管理资源时对于内存的优化示例:
spark-submit \
--master yarn \
--deploy-mode cluster \
--class com.rm1024.TotalPriceTop10 \
--driver-memory 3g \
--num-executors 8 \
--executor-memory 5g \
--executor-cores 1 \
--queue default \
--conf spark.default.parallelism=1000 \
--conf spark.storage.memoryFraction=0.6 \
--conf spark.storage.safetyFraction=0.9 \
--conf spark.shuffle.memoryFraction=0.4 \
--conf spark.shuffle.safetyFraction=0.8 \
spark-1.0-jar-with-dependencies.jar \
/tmp/ljy/data/infos /tmp/ljy/data/shopings 10
Spark2.0以后新型 JVM Heap 分成三个部分:Reserved Memory 、User
Memory 、Spark Memory。
Reserved Memory :默认都是300MB,这个数字一般都是固定不变的,在系统运行的时候Java Heap 的大小至少为 Heap Reserved Memory x 1.5 即 300MB x 1.5 = 450MB的JVM配置。
SparkMemory空间:默认是占HeapSize的60%,这个参数也是可以配置的,spark.memory.fraction来配置,系统框架运行时需要使用的空间,这是从两部分构成的,分别是StorageMemory和ExecutionMemory,默认情况下Storage和Execution各占该空间的50% 。
UserMemory:Saprk程序产生的临时数据或者是自己维护的一些数据结构也需要给予它一部分的存储空间,可以认为这是程序运行时用户可以主导的空间,叫用户操作空间。它占用的空间是(Java Heap - Reserved Memory) x 40%(默认是40%,可以有参数供调优),这样设计可以让用户操作时所需要的空间与系统框架运行时所需的空间分离开。有时在处理数据时单个Task内部所有算子使用的数据空间的大小大于此配置时就会出现OOM。
spark-submit \
--master yarn \
--deploy-mode cluster \
--class com.rm1024.TotalPriceTop10 \
--driver-memory 3g \
--num-executors 8 \
--executor-memory 5g \
--executor-cores 1 \
--queue default \
--conf spark.memory.fraction 0.7 \ 降低此值会降低spark.memory同时提高UserMemory内存
--conf spark.memory.storageFraction 0.5 \ 此参数会有关Shuffle与cache的内存比例,根据Shuffle与cacheRdd的业务来调优
spark-1.0-jar-with-dependencies.jar \
/tmp/ljy/data/infos /tmp/ljy/data/shopings 10
spark.shuffle.manager
spark.shuffle.io.preferDirectBufs
序列化在分布式系统中扮演着重要的角色,优化Spark程序时,首当其冲的就是对序列化方式的优化。Spark为使用者提供两种序列化方式:
Java serialization: 默认的序列化方式。
Kryo serialization: 相较于 Java serialization 的方式,速度更快,空间占用更小,但并不支持所有的序列化格式,同时使用的时候需要注册class。spark-sql中默认使用的是kyro的序列化方式。
配置:
可以在Saprk-default.conf设置全局参数,也可以在代码的初始化时对SaprkConf设置。该参数会同时作用于机器之间数据的shuffle操作以及序列化rdd到磁盘、内存。
Saprk不将Kyro设置成默认的序列化方式是因为需要对类进行注册,官方强烈建议在一些网络数据传输很大的应用中使用kyro序列化。
val conf = new SparkConf()
conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
conf.set("spark.kryo.registrationRequired", "true")
conf.registerKryoClasses(Array(classOf[MyClass1],classOf[MyClass2]))
val sc = new SparkContext(conf)
如果你需要系列化的对象比较大,可以增加参数spark.kryoserializer.buffer所设置的值。
如果你没有注册需要序列化的class,Kyro依然可以正常工作,但会但会存储每个对象的全类名(full class name),这样的使用方式往往比默认的 Java serialization 还要浪费更多的空间。
可以设置spark.kryo.registrationRequired 参数为 true,使用kyro时如果在应用中有类没有进行注册则会报错,通过报错把对应的类进行注册。
spark.shuffle.compress
spark.shuffle.spill.compress
spark.shuffle.accurateBlockThreshold
spark.io.compression.codec
官方提供了四种压缩方式:
压缩方式 | 默认值 | 类名全路径 |
---|---|---|
lz4 | true | org.apache.spark.io.LZ4CompressionCodec |
lzf | false | org.apache.spark.io.LZFCompressionCodec |
snappy | false | org.apache.spark.io.SnappyCompressionCodec |
zstd | false | org.apache.spark.io.ZStdCompressionCodec |
具体调优就是CPU和压缩率的权衡取舍以及网络、磁盘的能力和负载。对于RDD Cache的场合来说,绝大多数场合都是内存操作或者本地操作,所以CPU负载问题可能比IO问题更加突出。
以下三个参数的默认值均为32K,在压缩时用到的块的大小,降低这个块的大小也会降低Shuffle内存的使用率。
spark.io.compression.lz4.blockSize
spark.io.compression.snappy.blockSize
spark.io.compression.zstd.bufferSize
spark-submit \
--master yarn \
--deploy-mode cluster \
--class com.rm1024.TotalPriceTop10 \
--driver-memory 3g \
--num-executors 8 \
--executor-memory 5g \
--executor-cores 1 \
--queue default \
--conf spark.io.compression.lz4.blockSize 64k \
spark-1.0-jar-with-dependencies.jar \
/tmp/ljy/data/infos /tmp/ljy/data/shopings 10
配置参数 | 调优建议 |
---|---|
spark.reducer.maxSizeInFlight | 当集群单台机器有大量内存的时候可以适当的调高此参数来提高Shuffle的请求效率,建议采用默认值 |
spark.reducer.maxReqsInFlight | linux作为系统,当运行高并发TCP程序时避免单台机器的IO限制导致机器性能下降影响整体的工作效率建议调低此值,此配置一般会用在大型集群,建议采用默认值 |
spark.reducer.maxBlocksInFlightPerAddress | linux作为系统,当运行高并发TCP程序时避免单台机器的IO限制导致机器性能下降影响整体的工作效率建议调低此值,此配置一般会用在大型集群,建议采用默认值 |
spark.maxRemoteBlockSizeFetchToMem | 建议采用默认值 |
spark.shuffle.io.numConnectionsPerPeer | 建议采用默认值 |
spark.shuffle.io.maxRetries | 建议采用默认值 |
spark.shuffle.io.retryWait | 在集群任务比较繁重时可以适当的提高此参数以增加集群的稳定性,建议采用默认值 |
spark.shuffle.registration.timeout | 在集群任务比较繁重时可以适当的提高此参数以增加集群的稳定性,建议采用默认值 |
spark.shuffle.registration.maxAttempts | 建议采用默认值 |
spark.shuffle.maxChunksBeingTransferred | 当集群达到一定规模时应考虑降低此参数,避免单台机器出现负载过重影响整体性能建议采用默认值 |
spark.shuffle.service.enabled | 独立的Shuffle服务进程,在进行流处理时建议开启并开启资源的动态分配,在流量的低谷与高峰时对资源的释放建议采用默认值 |
spark.shuffle.file.buffer此参数默认值32K,建议调大此参数以减少对磁盘IO的操作以及对文件的查找。
spark-submit \
--master yarn \
--deploy-mode cluster \
--class com.rm1024.TotalPriceTop10 \
--driver-memory 3g \
--num-executors 8 \
--executor-memory 5g \
--executor-cores 1 \
--queue default \
--conf spark.shuffle.file.buffer 64k \
spark-1.0-jar-with-dependencies.jar \
/tmp/ljy/data/infos /tmp/ljy/data/shopings 10