MR
前言
Apache Hive 经过多年的发展,目前基本已经成了业界构建超大规模数据仓库的事实标准和数据处理工具,Hive已经不单单是一个技术组件,而是一种设计理念。Hive有JDBC客户端,支持标准JDBC接口访问的HiveServer2服务器,管理元数据服务的Hive Metastore,以及任务以MapReduce分布式任务运行在YARN上。
标准的JDBC接口,标准的SQL服务器,分布式任务执行,以及元数据中心,这一系列组合让Hive完整的具备了构建一个企业级数据仓库的所有特性,并且Hive的SQL服务器是目前使用最广泛的标准服务器。
虽然Hive有非常明显的优点,可以找出完全替代Hive的组件寥寥无几,但是并不等于Hive在目前阶段是一个完全满足企业业务要求的组件,很多时候选择Hive出发点并不是因为Hive很好的支持了企业需求,单单是因为暂时找不到一个能支撑企业诉求的替代服务。
EMR
企业级数仓构建需求
数仓架构通常是一个企业数据分析的起点,在数仓之下会再有一层数据湖,用来做异构数据的存储以及数据的冷备份。但是也有很多企业,特别是几乎完全以结构化数据为主的企业在实施上会把数据湖和企业数仓库合并,基于某个数仓平台合二为一。
企业在考虑构建自身数仓体系的时候,虽然需要参考现有的行业技术体系,以及可以选择的组件服务,但是不能太过于局限于组件本身,寻找100%开箱即用的产品。太过于局限于寻找完全契合的组件服务必然受限于服务本身的实现,给未来扩展留下巨大的约束。
企业数据仓库架构必然不等于一个组件,大部分企业在数仓架构实施的都是都是基于现有的部分方案,进行基于自己业务合适的方向进行部分开发与定制,从而达到一个半自研的稳态,既能跟上业务变化的速度,又不过于依赖和受限于组件自身的发展。
一般来说企业级数仓架构设计与选型的时候需要从以下几个纬度思考:
对于企业数仓架构来说,最重要的是如何基于企业业务流程来设计架构,而不是基于某个组件来扩展架构。
一个企业数仓的整体逻辑如上图所示,数仓在构建的时候通常需要ETL处理和分层设计,基于业务系统采集的结构化和非结构化数据进行各种ETL处理成为DWD层,再基于DWD层设计上层的数据模型层,形成DM,中间会有DWB/DWS作为部分中间过程数据。
从技术选型来说,从数据源的ETL到数据模型的构建通常需要长时任务,也就是整个任务的运行时间通常是小时及以上级别。而DM层主要是支持业务的需求,对实效性要求比较高,通常运行在DM层上的任务时间在分钟作为单位。
基于如上的分层设计的架构图可以发现,虽然目前有非常多的组件,像Presto、Doris、ClickHouse等等,但是这些组件各自工作在不同的场景下,像数仓构建和交互式分析就是两个典型的场景。
交互式分析强调的是时效性,一个查询可以快速出结果,像Presto、Doris、ClickHouse虽然也可以处理海量数据,甚至达到PB及以上,但是主要还是是用在交互式分析上,也就是基于数据仓库的DM层,给用户提供基于业务的交互式分析查询,方便用户快速进行探索。
由于这类引擎更聚焦在交互式分析上,因此对于长时任务的支持度并不友好,为了达到快速获取计算结果,这类引擎重度依赖内存资源,需要给这类服务配置很高的硬件资源,这类组件通常有着如下约束:
一旦发生任务异常,例如网络抖动引起的任务失败,机器宕机引起的节点丢失,再次重试所消耗的时间几乎等于全新重新提交一个任务,在分布式任务的背景下,任务运行的时间越长,出现错误的概率越高,对于此类组件的使用业界最佳实践的建议也是不超过30分钟左右的查询使用这类引擎是比较合适的。
而在离线数仓场景下,几乎所有任务都是长时任务,也就是任务运行时常在小时及以上,这时就要求执行ETL和构建数仓模型的组件服务需要具有较高的容错性和稳定性,当任务发生错误的时候可以以低成本的方式快速恢复,尽可能避免因为部分节点状态异常导致整个任务完全失败。
可以发现在这样的诉求下类似于Presto、Doris、ClickHouse就很难满足这样的要求,而像Hive、Spark这类计算引擎依托于Yarn做资源管理,对于分布式任务的重试,调度,切换有着非常可靠的保证。
Hive、Spark等组件自身基于可重算的数据落盘机制,确保某个节点出现故障或者部分任务失败后可以快速进行恢复。数据保存于HDFS等分布式存储系统上,自身不管理数据,具有极高的稳定性和容错处理机制。
反过来,因为Hive、Spark 更善于处理这类批处理的长时任务,因此这类组件不擅长与上层的交互式分析,对于这种对于时效性要求更高的场景,都不能很好的满足。所以在考虑构建数仓的时候,通常会选择Hive、Spark等组件来负责,而在上层提供交互式分析查询的时候,通常会使用Presto、Doris、ClickHouse等组件。
归纳下来如下:
一个企业在实施数据平台的时候,由多个不同组件各自工作在不同的架构层中,无法相互取代,相互协作配合,承载整个企业的数据平台业务。
EMR
企业级数仓技术选择
google发表的三篇论文从存储,计算,检索三个方向阐述了海量数据下一种新的分布式数据加工处理技术,这三个方向被雅虎Nutch团队实现后贡献给Apache,也就是目前大家看到的HDFS,MapReduce和HBase,形成了早期Hadoop的三大利器。
然而这三大利器更聚焦在异构数据的信息提取处理上,没有提供对结构化数据很友好的类似SQL语法的分析入口,同时在编程态的支撑也不够友好,只有Map和Reduce两阶段,严重限制了业务处理的实现,雅虎团队也是爬虫相关业务孵化而出,可以看出Hadoop早期的三大套件有着如下特点:
Hive就是诞生在这样的较大的行业背景下,Hive的出现刚好弥补了Hadoop只能用来做离线数据处理这个缺陷,提供了一种常用的分析接口,并且提供了非常好的用户交互方式。
下图来自Hive官网,Hive整体架构如下:
Hive提供JDBC接口实现支持以编程形式进行交互,同时业内几乎所有SQL Client、开源或商业BI工具都支持通过标准JDBC的方式连接Hive,可以支持数据探索的动作,极大的丰富了大数据生态圈下的组件多样性,同时也降低了使用门槛,可以让熟悉SQL的人员低成本迁移。
基于这些设计非常好的特效,加上Hive经过这多年的逐步完善,发展到今天已经是一个非常稳定成熟的生产环境可用的数据仓库组件,甚至替代品都很难找到,因此使用Hive作为数据仓库的构建基础是一个非常好的选择。
如上图所示,其中有很多优点:
所以虽然Hive出现已经非常有很长时间了,但是依旧是数仓构建的首选,在整个数仓构建中随处可见Hive的身影。虽然Hive有种种优点,让人难以割舍,但是并不等于能很好的支撑企业业务需求。很多时候选择Hive仅仅是因为暂时没有其他可选的组件,如果自己从头开发一个,或者基于某个组件改造,成本又会远超企业预期,因此不得不继续选择使用Hive。
基于实践来看,Hive在构建企业数仓过程中存在的主要局限围绕在以下几个方面:
虽然Hive在以上局限层面也做了很多尝试,Hive On Spark,但是受限于Hive的架构,HiveServer2自身有自己的SQL解析引擎,为了兼容架构将解析后的结果直接翻译成Spark最底层的接口,整体性能反而提升不大。
除了Hive之外,还有非常多的其他优秀的组件,但是从企业数仓技术选型的视角来看,适合用来构建数据仓库的,目前只有Hive和Spark SQL相对更加合适,在这两个组件中,Spark SQL相对Hive的优势又更加明显。
EMR
SparkSQL如何支撑企业级数仓
Spark引擎因为自身强大的生态和方便的编程接口被广泛应用在数据处理场景下,Spark 提供的Spark SQL模块更是将使用Spark支撑企业数据仓库提供了一个良好的基础设施。
如上图所示,一个典型的数据仓库架构需要包含不同层次的模型构建。由于数据量大,数据结构异构等多种原因,大数据架构下的企业数仓构建抛弃了基于关系型数据库下的Cube设计,直接采用基于分布式任务进行处理来构建多层数据模型。因此对于构建企业数仓的服务来说,有着如下要求:
基于以上特性可以发现,在目前可选择的组件范围内,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交互式接口,又能提供更灵活的编程态接口。
从不同的企业级数仓构建视角来看,Hive带来的约束都越来越大,而Spark SQL的成熟度和发展趋势已经完全具备取代Hive来构建整个数仓,Spark SQL的优势集中体现在如下方面:
因此,完全基于使用Spark SQL来支撑企业级的数仓是完全可行的,并且在目前也被众多企业实践验证。
如上图所示,一个基于Spark SQL构建的企业数仓架构逻辑架构设计上包含以上几个部分,每一个Spark SQL 引擎都是一个服务器,Spark SQL引擎将自己的信息注册到Zookeeper中,SQL服务器基于Zookeeper中的Spark SQL引擎来执行客户端过来的请求,SQL 服务器是一个兼容Hive JDBC接口的服务器,在使用Spark SQL来支撑数仓构建的时需要重点考虑的实施点是:
使用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,该思路是非常优秀的,但是因为开发过程中有点太过于局限,导致依旧存在很多问题,主要体现在:
因此虽然Spark提供了Spark thrift server服务用来提供类似JDBC这样的接口交互方式,但是目前依旧缺乏很多生成功能,导致在生产环境使用的情况非常少,Spark thrift server更像是一个小众的半成品,小修小补的尝试着解决部分问题,但是没有给予一个彻底的方案,导致现在有点缺乏实际的生产应用。
字节跳动的数仓在2020年全面从Hive迁移至Spark SQL,除了组件层面的源码修改外,在使用层面也对Spark 做了非常多的优化。 在下一次连载推送中,将重点介绍字节跳动数据平台在通过SparkSQL进行企业级数仓建设的实践。