前言
经过多年的发展,Hive已基本成为业界构建超大规模数据仓库的事实标准和数据处理工具。Hive 不仅仅是一个技术组件,而是一个设计理念。Hive 有一个 JDBC 客户端,一个支持标准 JDBC 接口访问的服务器,一个管理元数据服务的 Hive,以及在 YARN 上作为分布式任务运行的任务。
标准的 JDBC 接口、标准的 SQL 服务器、分布式任务执行和元数据中心,这一系列的组合使得 Hive 完全具备了构建企业级数据仓库的所有特性,而 Hive 的 SQL 服务器是目前使用最广泛的标准服务器。
虽然 Hive 的优势非常明显,但是能够完全替代 Hive 的组件很少,但这并不意味着 Hive 是一个完全满足现阶段企业业务需求的组件。很多情况下,选择Hive的出发点并不是因为Hive很好地支持了企业的需求,只是因为暂时没有替代的服务可以支持企业的需求。
企业级数仓建设要求
数据仓库架构通常是企业数据分析的起点。在数据仓库之下,还有一层数据湖,用于存储异构数据和冷备份数据。但是也有很多企业,尤其是几乎完全基于结构化数据的企业,在实现上会将数据湖和企业数据仓库合并,基于数据仓库平台将两者合二为一。
企业在考虑构建自己的数据仓库系统时,虽然需要参考现有的行业技术体系和可以选择的组件服务,但也不能过于局限于组件本身,寻找100%out-of-开箱即用的产品。太有限而找不到完全兼容的组件服务,势必会受限于服务本身的实现,给未来的扩展留下巨大的制约。企业数据仓库架构不一定等于一个组件。大部分企业在现有解决方案的基础上实现部分数据仓库架构,根据自身业务的合适方向进行部分开发和定制,从而达到半自主开发的稳定状态,
一般来说,在设计和选择企业级数据仓库架构时,我们需要考虑以下几个维度:
对于企业数据仓库架构来说,最重要的是如何根据企业业务流程来设计架构,而不是基于某个组件来扩展架构。
企业数据仓库的整体逻辑如上图所示。在构建数据仓库时,通常需要进行ETL处理和层次化设计。基于业务系统收集的结构化和非结构化数据进行各种ETL处理,成为DWD层。DWD层设计上层数据模型层形成DM,中间会有DWB/DWS作为中间过程数据的一部分。
从技术选型来看,从数据源的ETL构建数据模型通常需要长期的任务,即整个任务的运行时间通常为数小时以上。DM层主要支持业务的需求,对时效性要求比较高。通常,在 DM 层上运行的任务时间以分钟为单位。
基于上述分层设计的架构图可以发现,虽然目前有很多组件,比如Doris、Hive等,但是这些组件工作在不同的场景,比如数据仓库的构建和交互分析。一个典型的场景。
交互式分析强调及时性。查询可以快速产生结果。虽然也可以处理海量数据,甚至达到PB以上,但主要用于交互分析,即基于数据仓库的DM。该层为用户提供基于业务的交互式分析和查询,方便用户快速探索。因为这类引擎更注重交互分析,对长期任务不友好。这类引擎为了快速得到计算结果,对内存资源的依赖很大,需要为这类业务配置较高的硬件资源。,此类组件通常具有以下约束:
一旦出现任务异常,比如网络抖动导致任务失败,或者机器宕机导致节点丢失,再次重试所消耗的时间几乎等于重新提交一个任务。在分布式任务的上下文中,任务运行的时间越长,出错的概率就越高。对于此类组件的使用,行业最佳实践建议是在 30 分钟内查询并使用此类引擎更为合适。
在离线数仓场景中,几乎所有的任务都是长期任务,即任务运行时间超过一个小时。这时,执行ETL和构建数据仓库模型的组件服务需要具有高容错性和稳定性。当一个任务失败时,可以通过低成本的方式快速恢复,尽可能避免由于部分节点状态异常而导致整个任务完全失败。
可以发现,在这样的需求下很难满足这样的需求,而Hive、Spark等计算引擎依赖Yarn进行资源管理,对于分布式任务的重试、调度、切换非常可靠。保证。Hive、Spark等组件基于可重计算的数据磁盘机制,保证了节点故障或者部分任务故障可以快速恢复。数据存储在HDFS等分布式存储系统上,不对数据本身进行管理,具有非常高的稳定性和容错处理机制。
反之,由于 Hive 和 Spark 更擅长处理此类长期批处理任务,此类组件不擅长与上层交互分析,无法很好地满足此类对时效性要求较高的场景。. 因此,在考虑搭建数据仓库时,通常会选择Hive、Spark等组件来负责,而上层提供交互式分析查询时,通常会使用Doris、Doris等组件。
总结如下:
企业在实现数据平台时,多个不同的组件工作在不同的架构层,不能相互替代,相互配合,承载着整个企业的数据平台业务。
企业级仓库技术选型
发表的三篇论文分别从存储、计算和检索三个方向描述了海量数据下的一种新型分布式数据处理技术。这三个方向是雅虎 Nutch 团队在实施后贡献出来的,也是现在大家看到的。HDFS、HBase形成了早期的三大武器。
然而,这三大工具更侧重于异构数据的信息提取和处理。它们不提供类似于对结构化数据友好的 SQL 语法的分析条目。同时,编程状态下的支持也不够友好。只有地图和两个阶段。限制业务处理的实现,雅虎团队也是从爬虫相关业务中孵化出来的。可以看出,早期的三个套件具有以下特点:
Hive就诞生在如此大的行业背景下。Hive的出现正好弥补了它只能用于离线数据处理的缺陷,提供了通用的分析接口,提供了非常好的用户交互方式。
Hive的整体架构如上图所示。Hive 提供了 JDBC 接口实现,以支持编程形式的交互。同时,业界几乎所有的SQL、开源或商业BI工具都支持通过标准JDBC连接Hive,可以支持数据探索,极大地丰富了大数据生态中组件的多样性,降低了使用门槛,让熟悉SQL的人低成本迁移。
基于这些非常好的特效,经过多年的逐步完善,Hive已经发展成为一个非常稳定成熟的数据仓库组件,可用于生产环境,甚至很难找到替代品。因此,Hive 被用作数据仓库。建立基地是一个很好的选择。
如上图所示,有很多优点:
因此,虽然Hive已经存在了很长时间,但它仍然是数据仓库建设的首选,在整个数据仓库建设中随处可见Hive的身影。虽然 Hive 有各种优势,很难放弃,但并不代表它能够很好地支持企业的业务需求。很多时候选择 Hive 只是因为暂时没有其他可选组件。如果你从头开发,或者基于某个组件重新构建,成本会远远超出公司的预期,所以你不得不继续使用 Hive。
从实践来看,Hive在企业数据仓库建设过程中的主要局限围绕以下几个方面:
虽然 Hive 在上述限制(Hive On Spark)上做了很多尝试,但受限于 Hive 的架构,有自己的 SQL 解析引擎。为了与架构兼容,将解析结果直接翻译成 Spark 的最底层接口。整体性能提升不大。
除了 Hive,还有很多其他优秀的组件。但从企业数据仓库技术选型来看,目前只有Hive和Spark SQL比较适合搭建数据仓库。在这两个组件中,Spark SQL 比 Hive 具有更明显的优势。
如何支持企业级仓库
Spark引擎因其强大的生态和便捷的编程接口被广泛应用于数据处理场景。Spark 提供的 Spark SQL 模块为使用 Spark 支持企业数据仓库提供了良好的基础设施。
如上图所示,一个典型的数据仓库架构需要包括不同层次的模型构建。由于数据量大、数据结构异构等多种原因,大数据架构下的企业数据仓库建设摒弃了关系型数据库下的Cube设计,直接采用基于分布式任务的处理,构建了多层数据模型。因此,对于构建企业数据仓库的服务,有以下要求:
基于以上特点可以发现,在目前可用的组件范围内,Spark SQL 比其他组件(甚至是 Hive)更适合此类任务。但是很多企业在设计架构的时候又不能放弃Spark SQL带来的丰富特性,又担心Spark SQL缺少Hive这样的SQL服务器,所以退回到Hive和Spark SQL两个组件共存的形式。,Hive退化为只提供服务,所以从很多实际现象来看,Hive的企业数据仓库建设已经成为过去,而Spark SQL用于数据仓库建设。
如上图所示,企业在建设数据仓库时,通过一条Spark SQL提供基于SQL接口的常驻服务。同时也可以直接提交Jar任务以Spark的方式运行,不仅可以提供标准的SQL交互接口,还可以提供更灵活的编程接口。
从不同的企业级数仓建设来看,Hive带来的约束越来越多,Spark SQL的成熟度和发展趋势已经完全取代Hive来构建整个数仓。Spark SQL的优势集中在以下几个方面:
因此,使用Spark SQL支持企业级数据仓库是完全可行的,也得到了很多企业的验证。
如上图所示,一个基于 Spark SQL 的企业级数据仓库架构设计为包含以上部分。每个 Spark SQL 引擎都是一个服务器。Spark SQL 引擎在其中注册自己的信息 Spark SQL 引擎用于执行来自客户端的请求。SQL 服务器是与 Hive JDBC 接口兼容的服务器。使用Spark SQL支持数据仓库建设需要考虑的实现点有:
使用 Spark SQL 支持企业级数据仓库的核心是如何提供一个有用的任务服务器来支持任务管理。任务管理服务器在逻辑上类似,但更轻量级,没有复杂繁重的 SQL 解析,也没有 Spark 的约束,Spark 本身就是一个 YARN 作业。企业可以根据自己的业务流程开发轻量级服务器。字节在这方面有着非常深厚的实践经验。同时他们也有自己的Spark SQL引擎服务器,可以关注后续动态。同时,业内其他公司也做过类似的工作,比如网易的开源。
整个架构图如上所示。基于Spark SQL,可以更好的弥补Spark在多租户、资源隔离、高可用等方面的不足。是一个真正能满足大部分生产环境场景的开源项目。但是设计考虑是如何弥补Spark的不足,目的是增强Spark SQL的能力,而不是设计一个可以替代Hive组件的服务。因此,遗留项目的迁移成本很高。Spark SQL 和 Hive 有两个不兼容的 SQL 集。如何在使用遗留系统时降低其迁移成本,将是一个非常大的工作量。
业界也有开源 Spark。这个思路很好,但是因为开发过程有点太局限了,还是有很多问题,主要体现在:
因此,Spark虽然提供了Spark服务,提供了类似JDBC的接口交互方式,但仍然缺少很多生成功能,导致在生产环境中使用的非常少。Spark更像是一个小众的半成品,有小修和小修。尝试解决了一些问题,但没有给出彻底的解决方案,导致有点缺乏实际的生产应用。
字节跳动 EMR 产品在 Spark SQL 优化实践 数据湖引擎集成
目前Hudi等数据湖引擎的使用越来越广泛楼宇自控扩展模块,很多B端客户在使用Spark SQL时也需要用到数据湖引擎。因此,字节 EMR 产品需要将数据湖引擎集成到 Spark SQL 中。在这个过程中遇到了很多问题。
首先,在与 Spark 集成时,体验和易用性都得到了优化。在使用 Spark SQL 的过程中,用户需要手动输入大量指令,需要找到对应的 spark- 包。这也是最常用的集成解决方案。. 我们的解决方案是在预安装过程中提前将相关的jar包放到spark jars目录下,这样用户只需要指定,不需要手动输出很多指令。
其次,在Spark和Hive的跨引擎分析场景下,Spark可以正常创建表,/Trono可以正常读写,而Hive不能正常读写。这个问题的官方文档并没有明确的描述。解决办法是修改Spark的配置。文件或者修改Hive的hive-site-spark配置,保证配置项..hive的值。在初始化的Spark中为true,这样Hive就可以正常读取Spark创建的表了。
问题本质上是为了支持Hive引擎,在整体设计上做了一些妥协。要实现Hive对格式化表的读写,需要显式指定Hive的Input/实现,而/Trono可以根据Hive自动识别表的格式进行识别。
在兼容性方面,由于0.12版本不支持.2,升级Spark的影响非常大,所以用社区的版本更新编译,兼容与 Spark 3.2 进行集成。
火花 SQL 服务器
虽然业界为Spark SQL提供的SQL服务器已经有Spark之类的工具,但是在一些B端客户的业务环境中,这些工具并不能完全满足需求,所以字节跳动EMR团队自己设计并实现了Spark SQL。主要关注以下场景:
如上图所示,SQL 是一个实现接口并提供标准 JDBC 访问接口的服务器。Spark SQL 引擎也实现了该接口。服务启动时,Spark SQL 引擎已经提交到 Yarn,处于等待状态。当业务任务到达时,SQL 会执行引擎过滤,匹配现有引擎,或者重新提交新引擎来执行任务。
SQL 支持常见的授权认证,例如,支持各种隔离级别。例如,每个业务 SQL 都会初始化一个 Spark SQL 引擎来接收任务。任务执行结束后,引擎将从 Yarn 中销毁。User 级别是让用户最初拥有 0-N 个引擎,驻留在 Yarn 中,并交替执行任务。
这样的服务器设计打破了 Spark 单一的、解耦的 SQL 服务和任务执行带来的限制。它还支持更细粒度的资源管理和跨队列任务提交。
它还与 Hive 接口兼容。用户可以通过以下方式访问服务器:
./bin/beeline -u "jdbc:hive2://emr-5fqkwudj144d2gc1k8hi-master-1/;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=midas/ha;auth=LDAP" -n emr_dev -pEMR123456emr
./bin/beeline -u "jdbc:hive2://emr-master-2:10005/default;auth=LDAP” -n test_sub -pEMR123456emr
HA 模式下的信息记录在 中,保存内容的格式与 中一致,保证了使用 Hive 的客户端可以直接访问 HA 模式下的服务器。
Spark SQL 多租户
在Hive任务执行过程中,服务承诺提供SQL服务器进行用户认证、权限判断、解析SQL生成最终执行计划,然后由MR引擎执行具体的分布式任务。
在这个过程中,它承担着非常重的责任,所以需要消耗大量的资源,所以会极大地影响用户的并发。对于分布式任务操作,其资源约束来自于 Yarn 作为资源管理器分配的资源,但受限于 Hive 架构的影响,导致并发用户数不能随着 Yarn 资源的增加而增加。.
在 Spark SQL 引擎中,SQL 解析被下推到引擎中,并与特定分布式任务的执行相结合,不需要单独的服务器进行 SQL 解析。也正是因为 Spark SQL 和 Hive 在解析模块结构上的不同,Hive On Spark 的模式会变得非常困难。
对于上述场景,字节跳动EMR团队重新设计的SQL 只负责接收任务,判断用户资源、权限和身份,然后将任务发送到运行在Yarn中的Spark SQL 。打破了Hive的并发受Yarn和Yarn约束的局面。只有 Yarn 的资源决定了用户的并发程度,大大降低了 Spark SQL 的资源需求,增强了它的稳定性。一个非常大的改进。
其次,引擎预热功能减少了任务执行的时间,提高了整体速度。引擎预热是指在服务启动时将 Spark SQL 引擎提交给 Yarn,并处于等待状态。当业务请求到达时,根据业务类型从已经准备好执行任务的引擎中选择一个引擎。
并非每个预热提交的引擎都会被选中执行。SQL 中有以下三种引擎隔离级别:
可以看出,只有在User和Open级别的引擎预热才会产生价值。预热可以节省 Spark 的时间。当用户数足够大时,组保存的时间越多,作为统计单位。
Spark SQL 事务支持
Hive 的事务强度是基于实现的,例如通过以下语法:
CREATE TABLE tm (a int, b int) stored as orc TBLPROPERTIES
('transactional'='true', 'transactional_properties'='insert_only')
事务是可以打开的,但是由于事务的管理是在服务器上,所以需要开启ACID的时候所有的请求都会受到影响,而且Spark SQL很好的集成和支持了Hudi,以及其他数据湖格式,所以在Spark中不需要在 SQL 中实现类似的事务机制。只需要在最终读取和处理数据时,使用 Hudi 等特性来达到支持事务的效果。
例如,对于支持的数据格式表,操作:
MERGE INTO prod.nyc.taxis ptUSING (SELECT * FROM staging.nyc.taxis) stON pt.id = st.idWHEN NOT MATCHED THEN INSERT *;
所以Spark SQL在集成的时候就具备了事务能力,加上SQL 就可以以极低的成本获得和Hive事务能力一样的好处,并且在Hive下没有任何约束。从这个架构设计上看,它完全可以替代Hive。另一方面,当用户数量增加,同时修改和更新数据时,很容易造成大量的小广播传输,导致OOM。虽然大广播也会有OOM问题,但是大广播可以通过阈值控制,而小广播阈值不生效。一旦数量增加,很容易造成OOM。字节EMR团队通过对小广播的组合和广播,解决了大量小广播的传播问题,
结尾
随着企业业务发展越来越复杂,需要更加灵活高效的数据仓库架构。在这样的业务驱动背景下,Hive 的局限性越来越明显,基于 Spark SQL 灵活构建数据仓库的方案将越来越成为主流。因此,企业在考虑构建数据仓库系统时,可以考虑如何基于Spark SQL构建自己的数据系统。Spark完善开放的生态,未来必然会有更多优秀的服务,形成围绕Spark的强大优势。