Spark调优之Shuffle调优 调节map端内存缓冲和reduce端内存占比

map端内存缓冲: spark.shuffle.file.buffer (map端内存缓冲,默认32kb)
reduce端内存占比: spark.shuffle.memoryFraction (reduce端内存占比,默认0.2,20%)

理论基础和问题背景:

首先需要声明的是,这两个参数会被认为是调节shuffle的不二选择,但事实是调节这两个参数会对shuffle调优有效果,但并不是决定性的。而往往,shuffle的性能也不是这两个参数单方面就能决定的。
Spark调优之Shuffle调优 调节map端内存缓冲和reduce端内存占比_第1张图片
默认情况下,shuffle的map task输出到磁盘文件时,都会统一先写入自己的内存缓冲区,这个缓冲区的默认大小是32k。当每次内存缓冲区满溢后,才会执行spill(溢写)操作,溢写到磁盘。(如上图)

shuffle的reduce task拉取到数据后,用hashmap的数据格式,先汇聚每个key对应的values,再针对每个key的values进行我们自定义的聚合操作。

reduce task在进行聚合操作时,使用的就是reduce task自己对应的executor内存,executor(就是jvm进程)堆内存。 默认executor划分给reduce task聚合的内存比例是0.2

问题来了,理论上0.2的内存比例可能不满足reduce task的内存需求,拉取过来的数据,可能在内存放不下,这时,内存放不下的数据都会spill(溢写)到磁盘。(如上图)

不良后果:

Map端task处理的数据量很大,但内存缓冲固定只有32kb,会出现什么状况?
内存缓冲不够,可能造成map端往磁盘文件的spill溢写, 发生大量磁盘IO,导致性能降低。
Reduce端聚合内存占比默认0.2,如果数据量很大,reduce task拉取过来的数据量很大,那么就会发生频繁的reduce聚合内存不够用,导致频繁spill操作,溢写到磁盘,导致多次磁盘IO,性能降低。

如何调优参数?

查看spark UI,如果spark集群是standalone模式,spark运行后,会显示一个spark UI地址,4040端口,点击进去,依次查看,每个stage的详情,executor,每个task 的shuffle read和shuffle write的量,shuffle的磁盘和内存,读写的数据量; 如果spark集群是yarn模式,,从yarn界面进去,点击对应的application,进入spark UI,依次查看。

如果看到shuffle磁盘的 read和write的量很大,就应该考虑调节shuffle参数。首先考虑开启合并map端输出文件(可参见笔者博客《Spark调优之Shuffle调优 合并map端输出文件》);再就是调节上面说的两个参数,调节原则:spark.shuffle.file.buffer,每扩大一倍,观察效果; spark.shuffle.memoryFraction,每提高0.1,观察效果。

两个参数不能调节的过大,因为内存资源是有限的固定的,这里调节过大了,其他使用内存的环节就会出问题。要从整体上把控集群的优化!

SparkConf SparkConf = new SparkConf()
						.set(“spark.shuffle.file.buffer ”, “0.3”)  // 默认是0.2(20%)
						.set(“spark.shuffle.memoryFraction ”, “64”)  // 默认是32kb

你可能感兴趣的:(spark,Hadoop生态)