火花存储器管理
当Spark执行一个应用时,Spark cluster会启动两个JVM进程,驱动程序和执行器。驱动负责创建SparkContext,提交任务,分发任务等。执行器负责计算任务,并将结果返回给驱动程序。同时,有必要为需要坚持的RDD提供存储。驱动端的内存管理比较简单,这里说的Spark内存管理是针对执行端的内存管理。
Spark内存管理包括静态内存管理和统一内存管理。Spark1.6之前使用静态内存管理,Spark1.6之后引入统一内存管理。
在静态内存管理中,存储内存、执行内存和其他内存的大小在Spark应用程序运行期间是固定的,但用户可以在应用程序启动前对其进行配置。
统一内存管理和静态内存管理的区别在于,存储内存和执行内存共享同一个空室,可以互相借用空室。
Spark1.6及以上版本默认使用统一内存管理。通过将参数spark.memory.useLegacyMode设置为true(默认值为false),可以使用静态内存管理。
一.具体细节
1.静态内存管理分布图
2.统一内存管理分布图
3.如何在reduce中处理OOM?
拉数据的时候,一次都放不下。放下就能溢出磁盘。
1)减少每次拉取的数据量。
2)增加洗牌聚合的记忆比例。
3)增加执行程序的总内存
4.无序调谐
Spark.shuffle.file.buffer默认值:32k参数说明:该参数用于设置shuffle写任务的BufferedOutputStream的缓冲区大小。在将数据写入磁盘文件之前,会先写入缓冲区,待缓冲区满后再溢出到磁盘。调优建议:如果作业的可用内存资源足够,可以适当增加这个参数的大小(比如64k,必须翻倍),这样可以减少shuffle write时磁盘文件溢出的次数,也可以减少磁盘IO的次数,从而提高性能。实践中发现,合理调整该参数,性能将提高1%~5%。Spark.reducer.maxSizeInFlight默认值:48m参数说明:该参数用于设置shuffle read任务的缓冲区大小,该缓冲区决定了一次可以拉取多少数据。调优建议:如果作业的可用内存资源足够,可以适当增加该参数的大小(例如96m),以减少数据拉取的次数,这样也可以减少网络传输的次数,提高性能。实践中发现,合理调整该参数,性能将提高1%~5%。Spark.shuffle.io.maxRetries默认值:3参数描述:当shuffle read任务从shuffle write任务所在的节点拉取自己的数据时,如果由于网络异常导致拉取失败,会自动重试。此参数表示最大重试次数。如果拉操作在指定的次数内失败,作业执行可能会失败。调优建议:对于那些涉及特别耗时的shuffle操作的作业,建议增加最大重试次数(比如60次),以避免JVM全gc或网络不稳定等因素导致的数据拉取失败。实践中发现,调整这个参数可以大大提高数据量巨大(几十亿到几百亿)的洗牌过程的稳定性。随机文件未找到任务调度程序不负责重试任务,但DAGScheduler负责重试stage spark。shuffle.io .重试等待。默认值:5s参数说明:具体解释同上。该参数表示每次重试拉取数据的等待间隔,默认值为5s。调优建议:建议增加间隔时间(如60s)以增加洗牌操作的稳定性。Spark.shuffle.memoryFraction默认值:0.2参数说明:该参数表示执行程序的内存中,分配给shuffle读取任务进行聚合的内存所占的比例,默认值为20%。调优建议:这个参数已经在资源参数调优中解释过了。如果有足够的内存,并且很少使用持久化操作,建议增加这个比例,给shuffle read的聚合操作更多的内存,避免聚合过程中因为内存不足导致频繁的磁盘读写。在实践中发现,合理调整这一参数可以使性能提高10%左右。Spark.shuffle.manager默认值:sort|hash参数说明:该参数用于设置ShuffleManager的类型。在Spark 1.5之后,有三个选项:hash、sort和钨排序。HashShuffleManager是Spark 1.2之前的默认选项,但Spark 1.2及以后的版本默认为SortShuffleManager。钨-sort类似于sort,但是它使用了Tunten计划中的堆外内存管理机制,使得内存的使用更加高效。调优建议:由于SortShuffleManager默认对数据进行排序,如果您的业务逻辑中需要这种排序机制,可以使用默认的SortShuffleManager;而如果你的业务逻辑不需要对数据进行排序,那么建议参考以下参数进行调优,通过旁路机制或者优化后的HashShuffleManager来避免排序操作,同时提供更好的磁盘读写性能。这里需要注意的是,钨-sort要慎用,因为之前已经发现了一些相应的bug。spark . shuffle . sort . bypassmergerthreshold默认值:200参数说明:ShuffleManager为SortShuffleManager时,如果shuffle读任务数小于此阈值(默认值为200),则在shuffle写过程中不会执行任何排序操作。而是以HashShuffleManager未优化的方式直接写入数据,但最后每个任务生成的所有临时磁盘文件都会合并成一个文件,单独创建一个索引文件。调优建议:使用SortShuffleManager时,如果确实不需要排序操作,建议将该参数调整为大于shuffle read任务数。此时会自动启用bypass机制,map端不会排序,从而降低排序的性能开销。但是这样的话还是会产生大量的磁盘文件,所以需要提高shuffle写性能。Spark.shuffle.consolidateFiles默认值:false参数说明:如果使用HashShuffleManager,则该参数有效。如果设置为true,会开启合并机制,shuffle write的输出文件会有很大的合并。当混洗读取任务数量极大时,该方法可以大大降低磁盘IO开销,提高性能。调优建议:如果真的不需要SortShuffleManager的排序机制,可以尝试手动将spark.shffle.manager参数指定为hash,使用HashShuffleManager并在旁路机制之外开启consolidate机制。在实践中试用发现,其性能比开启旁路机制的SortShuffleManager高10%~30%。
5.无序播放调谐设置
如何使用SparkShuffle调优配置项?
1)在代码中,不推荐,硬编码。
新SparkConf()。set("spark.shuffle.file.buffer "," 64 ")
2)提交spark任务时,推荐使用。
spark-submit-conf spark . shuffle . file . buffer = 64–conf…
3)在conf下的spark-default.conf配置文件中,不建议使用,因为写完后所有应用都使用。