查看原文
其他

观点|SparkSQL在企业级数仓建设的优势

数据平台EMR团队 字节跳动数据平台
2024-09-10


企业级数仓架构设计与选型的时候需要从开发的便利性、生态、解耦程度、性能、 安全这几个纬度思考。本系列分两次连载,第一部分(本文)分享我们在企业级数仓建设上的技术选型观点,第二个部分则重点介绍了字节跳动数据平台在通过SparkSQL进行企业级数仓建设的实践。


文 | 惊帆 来自 字节跳动数据平台EMR团队

EMR

前言
Apache Hive 经过多年的发展,目前基本已经成了业界构建超大规模数据仓库的事实标准数据处理工具,Hive已经不单单是一个技术组件,而是一种设计理念。Hive有JDBC客户端,支持标准JDBC接口访问的HiveServer2服务器,管理元数据服务的Hive Metastore,以及任务以MapReduce分布式任务运行在YARN上。

标准的JDBC接口,标准的SQL服务器,分布式任务执行,以及元数据中心,这一系列组合让Hive完整的具备了构建一个企业级数据仓库的所有特性,并且Hive的SQL服务器是目前使用最广泛的标准服务器。

虽然Hive有非常明显的优点,可以找出完全替代Hive的组件寥寥无几,但是并不等于Hive在目前阶段是一个完全满足企业业务要求的组件,很多时候选择Hive出发点并不是因为Hive很好的支持了企业需求,单单是因为暂时找不到一个能支撑企业诉求的替代服务。 

EMR

企业级数仓构建需求

数仓架构通常是一个企业数据分析的起点,在数仓之下会再有一层数据湖,用来做异构数据的存储以及数据的冷备份。但是也有很多企业,特别是几乎完全以结构化数据为主的企业在实施上会把数据湖和企业数仓库合并,基于某个数仓平台合二为一。

企业在考虑构建自身数仓体系的时候,虽然需要参考现有的行业技术体系,以及可以选择的组件服务,但是不能太过于局限于组件本身,寻找100%开箱即用的产品。太过于局限于寻找完全契合的组件服务必然受限于服务本身的实现,给未来扩展留下巨大的约束。

企业数据仓库架构必然不等于一个组件,大部分企业在数仓架构实施的都是都是基于现有的部分方案,进行基于自己业务合适的方向进行部分开发与定制,从而达到一个半自研的稳态,既能跟上业务变化的速度,又不过于依赖和受限于组件自身的发展。

企业级数仓架构设计与选型维度

一般来说企业级数仓架构设计与选型的时候需要从以下几个纬度思考:
  • 开发的便利性:所选择的数仓架构是否具有很好的开发生态,可以提供不同类型的开发态接口,不限于SQL编辑器,代码提交,以及第三方工具整合。

  • 生态:所选择实现引擎自身是否有很好的生态功能,或者是否可以很好的与其他服务集成,例如数据湖引擎delta lake,icebeg,hudi等优秀组件出现,但是Hive集成的节奏却非常慢。

  • 解耦程度:分布式任务必然需要多个组件的协调,例如分布式存储,资源管理,调度等,像Hive就重度依赖于YARN体系,计算引擎也与MR强绑定,在解耦方面较弱,如果企业考虑在K8S上构建自己的计算引擎,Hive面临的局限会更加明显。

  • 性能:整体架构是否拥有更好的性能。

  • 安全:是否支持不同级别,不同力度的用户访问和数据安全鉴权体系。

    对于企业数仓架构来说,最重要的是如何基于企业业务流程来设计架构,而不是基于某个组件来扩展架构。 


    一个企业数仓的整体逻辑如上图所示,数仓在构建的时候通常需要ETL处理和分层设计,基于业务系统采集的结构化和非结构化数据进行各种ETL处理成为DWD层,再基于DWD层设计上层的数据模型层,形成DM,中间会有DWB/DWS作为部分中间过程数据。

    从技术选型来说,从数据源的ETL到数据模型的构建通常需要长时任务,也就是整个任务的运行时间通常是小时及以上级别。而DM层主要是支持业务的需求,对实效性要求比较高,通常运行在DM层上的任务时间在分钟作为单位。

    基于如上的分层设计的架构图可以发现,虽然目前有非常多的组件,像Presto、Doris、ClickHouse等等,但是这些组件各自工作在不同的场景下,像数仓构建和交互式分析就是两个典型的场景。

    交互式分析强调的是时效性一个查询可以快速出结果,像Presto、Doris、ClickHouse虽然也可以处理海量数据,甚至达到PB及以上,但是主要还是是用在交互式分析上,也就是基于数据仓库的DM层,给用户提供基于业务的交互式分析查询,方便用户快速进行探索。

    由于这类引擎更聚焦在交互式分析上,因此对于长时任务的支持度并不友好,为了达到快速获取计算结果,这类引擎重度依赖内存资源,需要给这类服务配置很高的硬件资源,这类组件通常有着如下约束:

    • 没有任务级的重试,失败了只能重跑Query,代价较高。

    • 一般全内存计算,无shuffle或shuffle不落盘,无法执行海量数据。

    • 架构为了查询速度快,执行前已经调度好了task执行的节点,节点故障无法重新调度。

      一旦发生任务异常,例如网络抖动引起的任务失败,机器宕机引起的节点丢失,再次重试所消耗的时间几乎等于全新重新提交一个任务,在分布式任务的背景下,任务运行的时间越长,出现错误的概率越高,对于此类组件的使用业界最佳实践的建议也是不超过30分钟左右的查询使用这类引擎是比较合适的。

      而在离线数仓场景下,几乎所有任务都是长时任务,也就是任务运行时常在小时及以上,这时就要求执行ETL和构建数仓模型的组件服务需要具有较高的容错性和稳定性,当任务发生错误的时候可以以低成本的方式快速恢复,尽可能避免因为部分节点状态异常导致整个任务完全失败。

      可以发现在这样的诉求下类似于Presto、Doris、ClickHouse就很难满足这样的要求,而像Hive、Spark这类计算引擎依托于Yarn做资源管理,对于分布式任务的重试,调度,切换有着非常可靠的保证。

      Hive、Spark等组件自身基于可重算的数据落盘机制,确保某个节点出现故障或者部分任务失败后可以快速进行恢复。数据保存于HDFS等分布式存储系统上,自身不管理数据,具有极高的稳定性和容错处理机制。

      反过来,因为Hive、Spark 更善于处理这类批处理的长时任务,因此这类组件不擅长与上层的交互式分析,对于这种对于时效性要求更高的场景,都不能很好的满足。所以在考虑构建数仓的时候,通常会选择Hive、Spark等组件来负责,而在上层提供交互式分析查询的时候,通常会使用Presto、Doris、ClickHouse等组件。

      归纳下来如下:

      • Presto、Doris、ClickHouse:更注重交互式分析,对单机资源配置要求很高,重度依赖内存,缺乏容错恢复,任务重试等机制,适合于30分钟以内的任务,通常工作在企业的DM层直接面向业务,处理业务需求。

      • Hive、Spark:更注重任务的稳定性,对网络,IO要求比较高,有着完善的中间临时文件落盘,节点任务失败的重试恢复,更加合适小时及以上的长时任务运行,工作在企业的的ETL和数据模型构建层,负责清洗和加工上层业务所需要的数据,用来支撑整个企业的数仓构建。

      一个企业在实施数据平台的时候,由多个不同组件各自工作在不同的架构层中,无法相互取代,相互协作配合,承载整个企业的数据平台业务。 

      EMR

      企业级数仓技术选择

      Google发表的三篇论文从存储,计算,检索三个方向阐述了海量数据下一种新的分布式数据加工处理技术,这三个方向被雅虎Nutch团队实现后贡献给Apache,也就是目前大家看到的HDFS,MapReduce和HBase,形成了早期Hadoop的三大利器。

      然而这三大利器更聚焦在异构数据的信息提取处理上,没有提供对结构化数据很友好的类似SQL语法的分析入口,同时在编程态的支撑也不够友好,只有Map和Reduce两阶段,严重限制了业务处理的实现,雅虎团队也是爬虫相关业务孵化而出,可以看出Hadoop早期的三大套件有着如下特点:

      • 门槛高,需要编程实现,并且编程态受限于MapReduce的两阶段约束。

      • 以离散数据处理为主,对分析能力,查询等常用数据分析功能支持不足。

      • 没有交互式客户端,无法实现交互式探索。

        Hive就是诞生在这样的较大的行业背景下,Hive的出现刚好弥补了Hadoop只能用来做离线数据处理这个缺陷,提供了一种常用的分析接口,并且提供了非常好的用户交互方式。 

        下图来自Hive官网,Hive整体架构如下:


        Hive提供JDBC接口实现支持以编程形式进行交互,同时业内几乎所有SQL Client、开源或商业BI工具都支持通过标准JDBC的方式连接Hive,可以支持数据探索的动作,极大的丰富了大数据生态圈下的组件多样性,同时也降低了使用门槛,可以让熟悉SQL的人员低成本迁移。 

        基于这些设计非常好的特效,加上Hive经过这多年的逐步完善,发展到今天已经是一个非常稳定成熟的生产环境可用的数据仓库组件,甚至替代品都很难找到,因此使用Hive作为数据仓库的构建基础是一个非常好的选择。

        如上图所示,其中有很多优点:

        • 稳定:稳定性是Hive一个非常让人称道的特性,很多时候虽然Hive的性能,计算速度不及其他引擎,但是Hive的稳定性却一直是非常好的。

        • 低门槛:只需要掌握基本的SQL技能,便可使用Hive进行开发,相比其他分布式计算引擎引擎成本更低。

        • 生态丰富:Hive和Hadoop生态圈紧密结合,而Hive自身的Metastore也成了大数据生态圈内的标准元数据服务,大部分引擎都支持直接适配MetaStore。

        • 扩展方便:Hive自身的UDF机制可以快速基于业务需要扩展功能。

        • 安全:Hive支持Kerberos/LDAP多种认证方式,并且和Ranger结合可以做到更细粒度的行列权限级别,拥有较好的数据安全。

        • 集成成本低:MapReduce只支持编程态的接口,并且不支持迭代计算,Hive封装了MapReduce提供SQL的接口,可以很低成本的和上层数据挖掘,数据分析工具进行集成。

          所以虽然Hive出现已经非常有很长时间了,但是依旧是数仓构建的首选,在整个数仓构建中随处可见Hive的身影。虽然Hive有种种优点,让人难以割舍,但是并不等于能很好的支撑企业业务需求。很多时候选择Hive仅仅是因为暂时没有其他可选的组件,如果自己从头开发一个,或者基于某个组件改造,成本又会远超企业预期,因此不得不继续选择使用Hive。

          Hive在构建企业数仓的局限

          基于实践来看,Hive在构建企业数仓过程中存在的主要局限围绕在以下几个方面:

          • 性能:Hive基于MapReduce虽然带来了非常好的稳定性,同时也降低了它的性能,虽然有TEZ做一定的优化,但是与同类的计算引擎Spark相比依旧有非常大的差距。

          • 资源配置:由于Hive底层使用MapReduce作为计算引擎,而MapReduce对SQL不友好,因此Hive在HiveServer2层面实现了SQL的转换处理,再生成基于MapReduce的物理计划,从而导致HiveServer2需要非常高的配置,才能维持足够好的稳定性。

          • 并发:Hive的并发受限于HiveServer2,企业需要维护多个高配的HiveServer2实例才能支持更好的并非,通常Hive的瓶颈都在HiveServer2而不是更底层的分布式计算。

          • 容错成本:Hive基于HiveServer2进行SQL的分析处理,多个HiveServer2之间相互独立不共享信息,因此当HiveServer2挂掉后,整个HiveServer2的任务都会结束,需要客户端自行重试,为整个作业级别的容错重启。

          • 事务支持:Hive的事务设置在HiveServer2上,一旦HiveServer2实例开启事务后,整个通过该HiveServer2的请求都会开启事务,整个事务成本过高。

          • 部署:如果企业的计算引擎部署是基于K8S等容器架构,Hive on K8S将会带来非常大的部署成本。

            虽然Hive在以上局限层面也做了很多尝试,Hive On Spark,但是受限于Hive的架构,HiveServer2自身有自己的SQL解析引擎,为了兼容架构将解析后的结果直接翻译成Spark最底层的接口,整体性能反而提升不大。

            除了Hive之外,还有非常多的其他优秀的组件,但是从企业数仓技术选型的视角来看,适合用来构建数据仓库的,目前只有Hive和Spark SQL相对更加合适,在这两个组件中,Spark SQL相对Hive的优势又更加明显。 

            EMR

            SparkSQL如何支撑企业级数仓

            Spark引擎因为自身强大的生态和方便的编程接口被广泛应用在数据处理场景下,Spark 提供的Spark SQL模块更是将使用Spark支撑企业数据仓库提供了一个良好的基础设施。

            如上图所示,一个典型的数据仓库架构需要包含不同层次的模型构建。由于数据量大,数据结构异构等多种原因,大数据架构下的企业数仓构建抛弃了基于关系型数据库下的Cube设计,直接采用基于分布式任务进行处理来构建多层数据模型。因此对于构建企业数仓的服务来说,有着如下要求:

            • 支持长时任务,通常是小时以上,天级别居多。

            • 支持多任务,也就是高并发。

            • 稳定性必须被保障。

            • 速度快。

            • 支持SQL的交互式接口。

            • 易于集成。

            • 支持任务的重跑和容错以及快速任务失败恢复。

            基于以上特性可以发现,在目前可选择的组件范围内,Spark SQL相比其他组件,乃至Hive更加合适承担这类任务。

            但是很多企业在进行架构设计的时候割舍不掉Spark SQL带来的丰富特性,又愁于Spark SQL缺乏类似Hive这样的SQL服务器,于是退而求其次变成Hive与Spark SQL两个组件共存的形态,Hive退化为仅仅提供MetaStore服务,因此从很多实践的现象来看,Hive构建企业数仓已是过去式,采用Spark SQL进行数据仓库的构建是众多的选择。

            如上图所示,企业在构建数仓的时候,通过一个Spark SQL Server提供基于SQL接口的常驻服务,同时也可以采用Spark Submit的方式直接提交Jar任务去运行,既能达到提供标准SQL交互式接口,又能提供更灵活的编程态接口。

            Spark SQL优势

            从不同的企业级数仓构建视角来看,Hive带来的约束都越来越大,而Spark SQL的成熟度和发展趋势已经完全具备取代Hive来构建整个数仓,Spark SQL的优势集中体现在如下方面:

            • 丰富的生态:Spark不仅可以和很多组件集成,其自身拥有生态已经涵盖各个方面,从数据分析到机器学习和图计算。

            • 开放:Spark架构设计上非常开放,可以快速整合其他产品,例如相比Hive,在集成Iceberg,Hudi等特性方面就会开放很多。

            • 部署:Spark既可以部署在ECS虚拟机上,也可部署在K8S架构上,多种部署形态非常灵活。

            • 性能:Spark的机制的流批处理性能非常合适用来构建企业数仓。

            • 易于开发:Spark SQL既有SQL接口,也支持灵活的可迭代编程接口,非常方便不同场景下的数据开发。

            • 安全:Spark SQL 可和不同的安全服务集成,实现细粒度的鉴权。

              因此,完全基于使用Spark SQL来支撑企业级的数仓是完全可行的,并且在目前也被众多企业实践验证。

              如上图所示,一个基于Spark SQL构建的企业数仓架构逻辑架构设计上包含以上几个部分,每一个Spark SQL 引擎都是一个服务器,Spark SQL引擎将自己的信息注册到Zookeeper中,SQL服务器基于Zookeeper中的Spark SQL引擎来执行客户端过来的请求,SQL 服务器是一个兼容Hive JDBC接口的服务器,在使用Spark SQL来支撑数仓构建的时需要重点考虑的实施点是:

              • 如何提供一个交互服务用来支撑不同的客户端来连接,包括交互式的beeline,以及编程态的JDBC和工具接口。

              • 如何打通权限对接,如果是Ranger的话需要的是Spark SQL Ranger Plugin。

              • 如何支持跨多个队列的任务提交。

                使用Spark SQL支撑企业级数仓的核心的地方还是在于如何提供一个好用的任务服务器,用来支撑任务的管理。任务管理服务器在逻辑上与HiveServer2相似,但是更加的轻量,没有HiveServe2中复杂而繁重的SQL解析,同时又没有Spark Thrift Server这种自身就是一个YARN作业的约束。企业可以基于自身的业务流程,开发一个轻量的服务器,在这方面字节有非常深的实践经验,同时也有自己的Spark SQL 引擎服务器,可关注后续的动态。

                同时业界也有其他企业做了类似的工作,例如网易开源的Kyuubi。


                备注:图片来自kyuubi官网:https://github.com/apache/incubator-kyuubi

                Kyuubi整个架构图如上所示,Kyuubi基于Spark SQL之上,较好的弥补了Spark Thrift Server在多租户、资源隔离和高可用等方面的不足,是一个真正可以满足大多数生产环境场景的开源项目。但是Kyuubi在设计的时候考虑的是如何弥补Spark Thrift Server的不足,目的在于增强Spark SQL的能力,而不是对等设计一个可以替换Hive组件的服务。因此对于遗留项目来说迁移成本较高,Spark SQL与Hive有着两套不兼容的SQL,在使用Kyuubi的时候如何是遗留系统迁移成本将是一个非常大的工作量。

                而行业也有开源的Spark Thrift Server,该思路是非常优秀的,但是因为开发过程中有点太过于局限,导致依旧存在很多问题,主要体现在:

                • Driver单点:整个Spark thrift server以一个Spark任务的形式运行在YARN上,所有的请求都运行在一个Driver中,一旦Driver挂掉后,所有任务都会同时失败。

                • 资源隔离:因为Spark thrift server是以Spark任务的形式运行在YARN上,因此提交的任务如果有跨队列提交需求的时候,Spark thrift server很难支撑,其次多个任务运行在同一个Driver之中,资源使用会相互影响,很难更精细化的进行资源的管理。

                • 多租户:Spark thrift server从请求层面是可以支持多用户的,但是从架构层面来看Spark thrift server是一个运行在Yarn上的任务,它也有自己的Application Id有自己的任务提交者,因此它实际上是以一个超级管理员的身份运行,再做二次租户隔离,必然存在一定的资源安全问题。

                • 高可用:Spark thrift server本身是没有高可用涉及的,因此它的高可用需要自行单独设计,且还得考虑客户端的兼容,例如Hive JDBC将HA信息存储在ZK中,而Spark thrift server没有这样的机制,因此高可用的实施成本较高。

                因此虽然Spark提供了Spark thrift server服务用来提供类似JDBC这样的接口交互方式,但是目前依旧缺乏很多生成功能,导致在生产环境使用的情况非常少,Spark thrift server更像是一个小众的半成品,小修小补的尝试着解决部分问题,但是没有给予一个彻底的方案,导致现在有点缺乏实际的生产应用。 

                字节跳动的数仓在2020年全面从Hive迁移至Spark SQL,除了组件层面的源码修改外,在使用层面也对Spark 做了非常多的优化。 在下一次连载推送中,将重点介绍字节跳动数据平台在通过SparkSQL进行企业级数仓建设的实践。

                关于我们在企业级数仓建设的经部分经验已通过火山引擎 E-MapReduce向企业开放。

                点击阅读原文了解火山引擎 E-MapReduce

                产品介绍

                火山引擎 E-MapReduce

                支持构建开源Hadoop生态的企业级大数据分析系统,完全兼容开源,提供 Hadoop、Spark、Hive、Flink集成和管理,帮助用户轻松完成企业大数据平台的构建,降低运维门槛,快速形成大数据分析能力。后台回复数字“3”了解产品

                - End -

                继续滑动看下一个
                字节跳动数据平台
                向上滑动看下一个

                您可能也对以下帖子感兴趣

                文章有问题?点此查看未经处理的缓存