spark集群调优心得

(2017年11月26日)


最近公司搞一个spark集群项目,期间会对spark集群进行调优.虽然调优的建议网上有很多,但是通过具体实践,发现不同的场景,调节的参数还是有不一样的地方.现记录一下最近学到的一些实践手段吧.

(1)要留一点资源给除spark以外的应用.

我们用的是Spark-On-Yarn资源调度,每台机器有24核心,每台机器最大内存有128G,

在yarn-site.xml里面,有人很可能把核心数和资源全部配上,以达到100%的利用率.实际上,这样反而会降低资源的效率,诱导集群出现不稳定的情况,比如tasks数开多了以后,出现卡顿,假死之类.每台机器应该留1-2核心,2g内存给其它的应用,比如yarn自身,linux系统自身.

(2) num-executors 与executor-cores 的权衡

num-executors 和 executor-cores之间的搭配很微妙,比如:

  1. num-executors 3 executor-cores 7

  2. num-executors 7 executor-cores 3

    上面2组对总的核心数的利用是一样的,但具体应用场景不一样.一般我们是优先使用第一种思路,我们还试过:

num-executors 2 executor-cores 11

num-executors 2 executor-cores 12

的搭配,这个对cpu的利用非常充足,而且也减少了executors之间通信的压力.同时,对系统并发的要求很高,我们的业务需要从HDFS上面读取数据,如果同时进行,会显著影响HDFS的读取速度,从而降低整体的执行效率.网上有资料上,在有HDFS做数据读写的情况下,executor-cores最好不超过5个,虽然本人觉得有些保守,可见并发执行对磁盘io操作影响还是比较大的.

第二种思路,可能正好相反,对HDFS的IO操作减小了一些,因为本人的理解是,executors执行,并不是并发的.虽然第一轮Stage,会同时生成许多tasks,tasks在同时工作,到第二轮Stage,executors会陆续完成tasks,不同executors里面的tasks的执行顺序,会有一个微小的时间差,因此并发多会稍微减小.当然这是本人的理解,实际上,当每个task执行的数据量很小时,这个时间差,应该是极小或不存在的,实际执行效率,可能比第一种还差.但是我们的业务中,每个task执行的数据颗粒度比较大,有1-100m之间,这个时间差应该会有.

(3)系统GC太慢,内存消耗太快

这个问题一直困扰着我们.我们用的是spark1.5版本,资料上说,spark的内存管理是交给jvm来做的.看起来,没法进行自定义.可是也不全是这样,在spark-defaults.conf 中,仍然可以对jvm调优.比如以下的一些配置:

-Xmn500m -XX:MaxTenuringThreshold=10 -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=10

-Xmn是每个新生代对象分配的内存,XX:MaxTenuringThreshold 是让年轻代对象在young gc 10次后进入年老代,默认是15次,这里是加快年轻代进入年老代的意思.然后使用 -XX:+UseConcMarkSweepGC的 XX:CMSInitiatingOccupancyFraction ,使其 在年老代使用率达到10%就触发父gc. 不过,这样频繁gc,也会增加cpu的使用时间.

尽管使用以上的jvm配置,实际执行中,并未发现有明显的gc行为,这倒令人感到奇怪.这个还得待研究一下.

上面所说的是通过调jvm,还有一种思路是周期重启sparkContext.也就是执行一定量的tasks之后,执行sparkContext.stop ,这个在我们的业务上,确实及时释放了一些内存资源.

当然,代码层面可调节的还有释放cache等,本人觉得在jvm上有很大的调整空间.

(4)一批tasks中偶尔有task执行耗时太长,假死,导致批处理任务无法正常进行的情况

这个问题也困扰我们很长时间.总结来说,就是程序稳定性不高.第一想到的,可能是数据倾斜,不过这个排除了.查看系统资源,发现cpu占用很小,内存也还有很多.随后,推测可能是网络阻塞,可是网络是光纤网,应该也不太可能.HDFS这时,也并未在并发任务中,磁盘IO 也不大可能有问题.虽然最后经过高人指点,解决了这个问题,不过,感觉这个问题,还需要深究一下.

当时的解决思路是,减小系统的并发度. 可是这样一来,对系统资源的利用效率,就相应低了一些.看了一些资料,做了些思考,既然cpu,内存都有空余,推测原因最大的,还是在tasks的网络通信上.因为出现类似FutureTask链接超时的情况频率比较大。


(2018.08.21更新)
后来,经过重新整理,反复调试,最终发现,原因是内存泄漏。实话说,这个原因当时比较意外。虽然之前有预感可能是这种情况,由于spark参数众多,系统环境复杂,很难定位具体问题点,使之前的种种推断流于猜测。要说总结出什么经验的话,那就是,最好有强有力的工具来辅助调试,检查程序,能够得出实证性的结论,才能提高调优效率。

你可能感兴趣的:(spark,大数据治理,调优)