导读:
大数据技术的发展历程中,继数据仓库、数据湖之后,大数据平台的又一革新技术——湖仓一体近年来开始引起业内关注。市场发展催生的数据管理需求一直是数据技术革新的动力。比如数据仓库如何存储不同结构的数据?数据湖又如何避免因为缺乏治理导致的数据杂乱现象?今天的文章想跟大家具体聊聊我们的数栈如何解决这些问题。
▫ 湖仓一体概念简述
▫ 数栈的湖仓建设过程中有哪些痛点
▫ 湖仓一体如何针对性解决这些问题
作者 / 土豆、小刀
编辑 / 向山
背景
随着进入21世纪第三个十年,大数据技术也从探索期、发展期逐渐迈向了普及期。现如今,越来越多的企业开始使用大数据技术辅助决策分析。数据仓库自1990年数据仓库之父比尔·恩门(Bill Inmon)提出以来,已经发展了三十余年,各大云厂商也纷纷推出如AWS Redshift、Google BigQuery、Snowflake等数据仓库。
但随着企业的现代化,各式各样的数据结构、越来越高的实时性、快速变化的数据模型等现实情况导致数据仓库已经不能满足日益增长的企业需求,以Iceberg、Hudi为代表的数据湖便应运而生。开放的文件存储、开放的文件格式、开放的元数据服务以及实时读取与写入等特点使它们受到大家的热烈追捧,各大云厂商也随之纷纷提出自己的数据湖解决方案,因此有人说,数据湖是下一代大数据平台。
新的事物总有两面性,一方面数据仓库无法容纳不同格式的数据,另一方面,数据湖缺乏结构和治理,会迅速沦为“数据沼泽”,两种技术均面临严重的局限性。在此背景下,融合了数据仓库与数据湖优点的新的架构模式"湖仓一体"被提了出来。
什么是湖仓一体
一言蔽之,“湖仓一体”是一种新的架构模式,它将数据仓库与数据湖的优势充分结合,其数据存储在数据湖低成本的存储架构之上,拥有数据湖数据格式的灵活性,又继承了数据仓库数据的治理能力。
数栈在湖仓一体上的演进
随着客户业务的不断发展,数栈作为一套数据中台也遇到了越来越多的挑战。在克服这些挑战的同时,我们也深感自身还有很多不足的地方。
数栈离线数仓
如图所示,用户业务数据通过FlinkX导入Hive数仓,通过Spark引擎处理业务逻辑,最终通过FlinkX再写回用户数据源。
数栈实时数仓
如图所示,实时数仓有两条链路:一条是实时链路,采集到的CDC数据写往消息队列,通过FlinkStreamSQL实时计算,最终写到Kudu、HBase等高效读写的数据源;另一条是准实时链路,采集到的CDC数据写往Hive表,通过Spark SQL计算。
引入数据湖
由于数栈流计算引擎使用的是Flink,在调研Iceberg、Hudi两款开源数据湖项目之后,Iceberg相比于Hudi来说,与Flink集成更便捷,生态上也更友好,因此我们决定采用Iceberg作为我们的第一款数据湖产品,后续将逐个支持Hudi等其他数据湖。关于Iceberg的一些特点这里就不过多赘述了,下面是引入数据湖后的数仓链路:
结构化、半结构化及非结构化的数据通过FlinkX做ETL处理后写入Iceberg数据湖或者写回消息队列。接着数据在消息队列和数据湖中通过Flink和Spark引擎不断流转与计算,最终写到Kudu、HBase等高效读写的数据源。
数栈在湖仓建设中的痛点
批流分离,运维费钱费力
目前离线数仓的做法是先使用FlinkX将数据采集到Hive表中,然后再通过Hive SQL或者Spark SQL计算,最后写回Hive;实时数仓的做法是数据从源表的Kafka中读取,通过FlinkStreamSQL计算,最后写到kudu或HBase。
在这两条链路中,开发人员首先不得不维护两套自研的框架:FlinkX和FlinkStreamSQL;运维人员不得不对Hive SQL、Spark SQL和Flink SQL任务有一定的了解;数据开发也不得不熟悉Hive SQL、Spark SQL和Flink SQL的语法及参数配置。这样的一整套数仓开发、使用、运维起来,成本不可谓不巨大。
代码重复,采算资源浪费
FlinkX和FlinkStreamSQL在创建之初,一个面向同步,一个面向计算。但随着业务的不断发展,这两个其实越来越相似了。FlinkX在同步时也需要做一定程度的计算,将数据清洗后写入目标表。而FlinkStreamSQL如果不进行计算只是单纯的写库,那么就是同步功能。
因此后续在新增数据源类型的时候,FlinkX和FlinkStreamSQL需要各增加一个类似的connector,而这个connector中80%的代码都是相似的。在面对数据源相关的bug时,FlinkX和FlinkStreamSQL都需要进行修复。两套框架所带来的是两倍的人力成本。
缺乏治理,湖仓变成沼泽
在引入Iceberg数据湖后,绝大部分数据都未经处理就写入进去了。由于缺乏catalog级别的元数据管理,想要从大量原始数据中找到想要的业务数据如同沙中淘金。不同的业务人员在使用完各自的数据后不知如何整理,就导致了数据杂乱不堪,并衍生出了大量的小文件。大量的小文件严重拖累了Hadoop集群的效率,使数据湖沦为了数据沼泽。
数栈迈向湖仓一体
痛点的解决方案
为了解决以上痛点,数栈做了以下改动:
1、启用Flink做主计算引擎
Flink在1.12版本实现了Source&Sink API的流批一体,并且社区也在不断向着流批一体的方向发展,因此我们选用Flink作为主要的计算引擎。至此,无论是离线、实时数仓还是数据湖,只需要一套Flink SQL任务即可完成业务的处理。得益于Flink在数据处理上的行业领先水平,我们可以基于Flink流批一体,使用Flink作为湖仓的主要计算引擎,一举解决运维成本高,操作难度大的问题。
2、融合代码重复的两套插件
如上文提到的,FlinkX与FlinkStreamSQL在插件层80%的代码是重复的,因此我们不需要维护两套重复的插件。我们将两套框架的优点相结合,写出了全新的FlinkX。融合后的FlinkX继承了原JSON的数据同步功能,并且也能使用强大的SQL语言。无论数据是离线的还是实时的,数据无论是入仓、入湖还是计算,借助全新的FlinkX均能轻易处理。
3、统一湖仓数据源心
引入数据源中心统一管理中台中使用到的数据源,可以方便中台管理员管理数据源,控制数据源的使用权限。同时将散列在各项目中的元数据模块统一到数据源中心中,可以方便使用者查看某数据源的使用情况。针对Iceberg数据湖数据源设置更细粒度的catalog管理,防止沦为数据沼泽。对于底层存储在HDFS上的数据源,如Hive、Iceberg等,增加小文件合并功能,手动的或自动的定时合并小文件,彻底解决小文件问题。
数栈湖仓一体架构
基于上述所说,让我们一起来看看,我们通过 Flinkx 将数据入湖(Iceberg)、入仓(hive) 之后,数栈上湖仓一体的结构是如何实现的:
在引入Iceberg 之后我们不仅可以统一对接各种格式的数据存储,包括结构化半结构化数据,并且底层存储上支持对OSS,S3,HDFS 等存储系统,而利用Iceberg 的特性也可以提供对ACID、表结构变更,基于Snapshot 读取历史数据等功能的支持,同时数栈在上一层统一了元数据中心,使用统一的元数据存储,不仅仅可以管理数据湖的存储,而且可以做到对原有的数据仓库进行统一管理,在表结构层做到统一入口,在上层计算的时候可以看到全局的表信息,而不是孤立的多个源的表信息。
在统一元数据之后,我们需要一个能基于已经构建的元数据之上对数据湖,数据仓库进行计算的工具,在Hadoop 生态上,类似的计算工具有很多,包括Trino,Flink,Spark等。当前这个结构上,我们可以根据客户的业务场景进行选择,如果客户已经有数据仓库,并且想借助数据湖来进行上层的业务构建的话,能支持跨源的Flink,Trino用来查询就是一个合适的选择,同时客户对查询交互性能有要求的话,那么Trino 的MPP 架构提供的横向扩展的特性就会是一个不错的选择。
数栈对于未来的展望
数栈当前通过引入Iceberg和改造FlinkX ,统一了实时和离线的数据集成和计算和存储能力,可以在数栈上实现基本的湖仓库一体。未来我们希望数栈具有跨源能力,不只是在单一的Hadoop 生态里面构建湖仓一体,而且可以基于企业已有的传统数据存储比如MySQL、Oracle仓库(不需要将数据从MySQL、Oracle 等仓库抽到统一的数据中心),通过统一的元数据中心注册不同的catalog进行隔离,加上新建设的数据湖,在上层的Flink计算引擎做到湖仓一体的能力。
在存储层,我们希望可以做到对当前HDFS和S3 的支持,同时也可以支持本地和云端存储;并且在存储层面我们要做到自动进行数据管理,包括对小文件进行定期合并,对远程文件数据进行加速,并对数据构建索引,统一的元数据管理等等;我们的目标是实现存储层的Data warehouse as a service。
要做到上面的规划,我们还有很多功能要去优化和整合,未来我们会实时关注和参与Iceberg、Hudi、Flink 社区,关注社区的规划和发展,结合我们当前已有的统一的数据开发平台进行不断的迭代,到达DasS的能力,让企业和用户能在湖仓一体的架构下提升数据价值。