前言
大家好,我是明哥!
公众号已经运维有一段时间了,也写了不少博文,其中很多是从自己解决真实线上问题的实战经历出发,写的经验总结和IT感悟。但由于前期摸索过程中,文风不统一且排版不太好,各篇博文之间也欠缺呼应,不太方便大家分类阅读学习,所以后续博文会尽量归类到对应的系列下。
本片博文是“大数据线上问题排查系列”大类别之一,以下是正文。
问题概述
某日测试团队同学跟我反馈了一个问题,即某大数据应用系统中HIVE离线计算作业脚本在CDH大数据平台跟TDH大数据平台的执行效率相差很大,经过验证该脚本在TDH大概需要 13 seconds,在CDH大概需要8 min 25 seconds,相差确实很大。
由于该大数据应用系统是是产品化的发包方案,在不同客户不同平台性能差异如此巨大,是不利于统一部署和运维的。所以需要对对该性能差异的背后原因,业务系统安装配置需注意的地方,以及业务代码侧潜在的应对方案,进行详尽的分析。
问题分析
问题分析的思路,仍然是查看相关大数据组件的WEB UI (在这里是 HIVE SERVER2 UI,和 YARN WEB UI), 业务系统及各中间件的日志 (涉及到业务系统日志,业务系统使用的到二方包三方包的日志,调度系统日志等),以及相关大数据组件的日志 (在这里是 HIVE SERVER2, HIVE METASTORE, YARN RESOURCE MANAGER, YARN TASK MANAGER等日志)。
顺着上述思路,该问题的原因很轻松就找到了: 通过 HIVE SERVER2 WEBUI 和 YARN WEB UI,发现该 HIVE 离线计算作业脚本在底层对应了多个SQL语句,这些SQL语句在CDH平台上是以 MR 任务的形式运行在 YARN 上的 (而不是预期的TEZ或SPARK)!
熟悉 MR/TEZ/SPARK 的小伙伴们,一般都有个笼统的印象,即 SPARK 比 MR 的速度一般是要快很多的,特别是在 SQL 底层对应多个子任务的时候。该问题的根本原因,其实就跟这个有关。
问题根本原因
- 同样的 HIVE SQL 在 CDH 与 TDH平台性能差异的根本原因,是作业执行机制的不同,在SQL底层对应大量小任务时该性能差异尤其明显,其实这也是星环对inceptor最引以为豪的地方;
- 在TDH中,sql 作业是以 hive on spark的模式运行的:sql经 hiveserver2解析编译优化一般会生成 spark任务,这些spark任务是在spark集群中执行的,该 spark 集群是在inceptor 集群启动时就启动好了的,而不是在有 spark 任务需要执行时再动态启动,且该spark集群 不受 yarn 资源管理框架的管控,默认的资源配置也很高(JVM堆空间是32G);
- 而在CDH中,sql作业是以 hive on mr/tez/spark的模式运行的:sql 经hiveserver2解析编译优化生成 mr/tez/spark任务,这些 mr/tez/spark 任务在执行时,首先需要向 yarn申请资源,然后在申请获得的多个 yarn container中启动多个 Jvm虚拟机,此后才可以在这些container中执行任务。由于向yarn申请资源需要花费时间,且jvm虚拟机的启动和销毁也需要花费时间,再加上作业默认配置的spark 资源需求不高,所以作业执行速度较TDH会有差异,在SQL底层对应多个小任务时,该差异尤其明显;
- 所以,HIVE SQL 在CDH中以MR引擎运行,跟TDH平台的速度差异特别大;当经过配置在CDH中以SPARK引擎运行时,跟TDH平台的速度差异会比MR引擎小,但仍会跟TDH平台有差异;
- 在我们的上述测试环境中,上述SQL脚本对应了29个底层任务,在CDH中是以 hive on mr的方式运行的,最小/最大/平均执行时间分别是8.8/48.2/18.5秒,在tdh中最小/最大/平局执行时间分别是177ms/2.98s/512ms,这其实是典型的大量小任务,所以性能差异比较明显。
- 从本质上来讲,TDH 是采用了预计算和空间换时间的思想,提前启动了 SPARK 集群,且改SPARK集群是以 STANDALONE 模式运行的跟YARN不会存在资源竞争,再加上该 SPARK 集群的 driver/excutor的memory和cpu等资源参数默认都比较高,所以作业执行效率会比CDH平台高。
问题解决方案
- 业务系统安装配置注意点:
- 我们无法改变CDH的执行机制,但由于 hive on spark有session的概念,且在同一个session内的所有sql底层的所有spark 任务都会复用同一个spark集群,所以配置使用hive on spark 而不是 hive on mr/tez,能尽量减少向yarn频繁申请资源的时间开销,以及虚拟机频繁启动和销毁的时间开销;(set hive.execution.engine=spark)
- 另外,配置业务系统使用用户指定的/合适的YARN资源队列而不是默认的资源队列,也是需要注意的地方;(set mapred.job.queue.name=xxx;或set mapreduce.job.queuename=xx)
- Spark任务的资源配置,需要针对不同客户的数据量和yarn队列资源数,以及该任务的复杂性,合理进行配置;(由于调度系统是以SQL脚本为单位进行调度的且很多调度系统都支持设置资源相关参数,建议在SQL脚本级别配置spark任务的具体资源参数,这些参数对sql脚本内部的多个sql语句都是有效的;如果多个SQL语句对资源有不同需求,建议划分到不同的SQL脚本中)
- 业务代码侧潜在的应对方案:
- 如果采用以上方案后,仍达不到客户的性能要求,业务代码测潜在的应对方案是,进一步拆分SQL脚本增大业务系统总体的并行度(一个SQL脚本中的多个SQL,是串行提交的,结合业务逻辑进一步拆分SQL语句到多个脚本,并并行提交这些SQL脚本,能提高业务系统整体的并行度,更大化地利用YARN集群资源 – 前提是yarn队列资源要够)
问题总结
同样的HQL,在CDH与TDH平台执行效率差异巨大的根本原因,是因为 TDH 采用了预计算和空间换时间的思想,提前启动了 SPARK 集群,且改SPARK集群是以 STANDALONE 模式运行的跟YARN不会存在资源竞争,再加上该 SPARK 集群的 driver/excutor的memory和cpu等资源参数默认都比较高,所以作业执行效率会比CDH平台高。
话说回来,凡事有利就有弊,TDH 将所有作业都运行在同一个 spark 集群中,作业相互之间就有资源的竞争相互之间会有影响;而在CDH中,不同客户端提交的SQL属于不同的 SESSION,每个SESSION都会有自己的SPARK ON YARN集群,相互之间资源隔离处理的更好影响也更小。
新的问题
抛出个问题,HIVE ON SPARK 模式下,各个SESSION背后的 SAARK 集群何时启动?何时关闭?会不会有处理不慎资源泄露,造成SPARK集群不能及时关闭浪费YARN资源,甚至极端情况下因YARN 集群资源被浪费没有新的资源新的作业无法提交的风险?
笔者确实在线上遇到了这种情况,后续会通过另一篇博文讲述下相关知识。小伙伴们可先行思考下。STAY TUNED.