spark的性能优化

因为之前在tesla集群上申请了1000个节点被喷之后,现在只敢申请100个节点,后来导致一个严重的结果,自从100节点以来再也没有跑出结果。。。。。。进而意识到了spark优化的重要性,现再次总结一下:
1.一个通用的调整并行度的方式:首先要明确一个概念,Hadoop为每一个partition创建一个task, 我们使用task数来控制并行度,默认情况下是有输入源(HDFS) block的数量来决定的,因为程序需要保证 datenode 尽量在使用该输入源的task里面,所以block决定着input split。所以默认情况可能会造成运行时间过长 或者Drive调度压力过大(数据太琐碎)

Spark.default.parallelism =申请资源CPU Cores总和2-3倍(一个core上运行2-3个task)

2.数据倾斜:在进行shuffle的时候,需要将各个节点上相同的key放到某一个节点上的task 来解决,比如 groupby 和join 操作都会引起shuffle 操作,如果某一个key对应的数据量特别大,就会发生数据倾斜,现象就是一些task很快完成,但是个别task会比较慢。这一部分很简单就能察觉:
duration time 是程序运行的时间,shuffle read 是给task分配的数据量。如果是数据倾斜我们从这两个上面就可以很明显的看出来(观察时间长的task 是不是分到的数据量比较大)

主要注意一下,spark中会有一个stage划分的问题,一般是根据shuffle来划分的,【 只要看到Spark代码中出现了一个shuffle类算子或者是Spark SQL的SQL语句中出现了会导致shuffle的语句(比如group by语句),那么就可以判定,以那个地方为界限划分出了前后两个stage。】,当然,如果你想知道每个key的分布情况,你可以先采集10%的样本数据,然后countByKey(),最后foreach打印:

具体的解决方法可以参考:
http://tech.meituan.com/spark-tuning-pro.html

3.一个RDD在经过一些数据处理之后,例如filter,过滤了较多的数据之后,建议使用coalesce,手动减少RDD的partition的数目,减少调度压力,提高程序效率。 

4.使用高性能的算子,在保证功能的前提下:
使用reducebykey替代groupbykey的trick,之前已经提到过,下面说一下其他常见的:
mapPartirion 代替map:一次函数会处理一个partition的所有数据,但是如果内存不够狠容易出现OOM。
foreachpartition代替foreach :与上述的原理相同。

5.对大型变量进行广播,当内部算子使用需要使用外部变量的时候,在不broadcast整个变量的时候,drive 就会将算子中需要的变量按照task 的数目进行拷贝,分给每个task一份,如果bc之后,则会把这个变量广播到每个executor中 

关于spark的各种参数调整和原理说明 见
http://tech.meituan.com/spark-tuning-basic.html

6.最后说一个重点,也是我这次改进的重点,就是在大表和一个比较小的表join的时候,such as:

usertable:5w个需要进行关联的user id;
featuretable:百亿条的feature数据;

此时,若我们选择小表 join 大表,所有数据需要进行shuffle ,需要大量的I/O操作,相同的key会放在同一个partition中。

使用bc会将小表分发到每个executor上面,因此关联都在本地完成。

具体的代码如下所示:

这里使用mappartition有两个原因: 因为里面要新建一个stuMap变量,而map是对每一条记录都会新建这样一个变量,但是mappartition是在针对每个partition新建一个stuMap;另外就是 他可以使匹配不上的记录不返回;

你可能感兴趣的:(hadoop,spark,性能优化)