桔妹导读:在滴滴SQL任务从Hive迁移到Spark后,Spark SQL任务占比提升至85%,任务运行时间节省40%,运行任务需要的计算资源节省21%,内存资源节省49%。在迁移过程中我们沉淀出一套迁移流程, 并且发现并解决了两个引擎在语法,UDF,性能和功能方面的差异。
1.
迁移背景
Spark自从2010年面世,到2020年已经经过十年的发展,现在已经发展为大数据批计算的首选引擎,在滴滴Spark是在2015年便开始落地使用,不过主要使用的场景是更多在数据挖掘和机器学习方向,对于数仓SQL方向,主要仍以Hive SQL为主。
下图是当前滴滴内部SQL任务的架构图,滴滴各个业务线的离线任务是通过一站式数据开发平台DataStudio调度的,DataStudio把SQL任务提交到HiveServer2或者Spark两种计算引擎上。两个计算引擎均依赖资源管理器YARN和文件系统HDFS。
在迁移之前我们面临的主要问题有:
SQL任务运行慢:迁移前SQL任务运行的平均时间是20分钟,主要原因是占比高达83%的Hive SQL任务运行时间长,Hive任务执行过程中会启动多个MR Job,Job间的中间结果存储在HDFS,所以同一个SQL, Hive比Spark执行的时间更长;
Hive SQL稳定性差:一个HS2会同时执行多个用户的Hive SQL任务,当一个异常任务导致HS2进程响应慢甚至异常退出时,运行在同一个实例的SQL任务也会运行缓慢甚至失败。而异常任务场景各异。我们曾经遇到的异常任务有多个大SQL加载过多的分区元数据导致HS2 FullGC,加载UDF时导致HS2进程core dump,UDF访问HDFS没有关闭流导致HS2机器端口被打满,这些没有通用解法, 问题很难收敛;
人力分散:两个引擎需要投入双倍的人力,在人员有限的情况下,对引擎的掌控力会减弱;
所以为了SQL任务运行更快,更稳,团队人力聚焦,对引擎有更强的掌控力,我们决定把Hive SQL迁移到Spark SQL。
2.
迁移方案概要设计
Hive SQL迁移到Spark SQL后需满足以下条件:
保证数据一致性,也就是相同的SQL使用Spark和Hive执行的结果应该是一样的;
保证用户有收益,也就是使用Spark执行SQL后应该节省资源,包括时间,cpu和memroy;
迁移过程对用户透明;
为了满足以上三个条件, 一个很直观的思路就是使用两个引擎执行用户SQL,然后对比每个引擎的执行结果和资源消耗。
为了不影响用户线上数据,使用两个引擎执行用户SQL有两个可选方案:
复用现有的SQL任务调度系统,再部署一套SQL任务调度系统用来迁移,这个系统与生产环境物理隔离;
开发一个SQL双跑工具,可以支持使用两个引擎执行同一个SQL任务;
下面详细介绍这两个方案:
▍1. 方案一:复用现有的SQL任务调度系统
再部署一套SQL任务执行系统用来使用Spark执行所有的SQL,包括HDFS,HiveServer2&MetaStore和Spark,DataStudio。新部署的系统需要周期性从生产环境同步任务信息,元数据信息和HDFS数据,在这个新部署的系统中把Hive SQL任务改成Spark SQL类型任务,这样一个用户的SQL在原有系统中使用Hive SQL执行,在新部署的系统中使用Spark执行。如下图所示,蓝色的表示需要新部署的子系统。
▍2. 方案二:开发一个SQL双跑工具
SQL双跑工具,可以线下使用两个引擎执行用户的SQL,具体流程如下:
SQL收集:用户的SQL是在HS2上执行的,所以理论上通过HS2可以收集到所有的SQL;
SQL改写:执行用户原始SQL会覆盖线上数据,所以在执行前需要改写SQL,把SQL的输出的库表名替换为用来迁移测试的的库表名;
SQL双跑:分别使用Hive和Spark执行改写后的SQL;
▍3. 方案对比
方案一
-
优势
隔离性好,单独的SQL执行系统不会影响生产任务,也不会影响业务数据;
劣势
-
需要的资源多:运行多个子系统需要较多物理资源;
部署复杂:部署多个子系统,需要多个不同的团队相互配合;
容易出错:子系统间需要周期性同步,任何一个子系统同步出问题,都可能导致执行SQL失败;
方案二
-
优势
非常轻量,不需要部署很多系统,而且对物理资源需要不高;
劣势
-
与生产公共一套环境,回放时有影响用户数据对风险;
需要开发SQL收集,SQL改写和SQL双跑系统;
经过权衡, 我们决定采用方案二, 因为:
通过HiveServer收集所有SQL,SQL改写和SQL双跑逻辑清晰,开发成本可控;
创建超读帐号,对所有库表有读权限,但只对用户迁移的测试库有写权