交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

本文由 T3 出行大数据平台负责人杨华和资深大数据平台开发工程师王祥虎先容 Flink、Kylin 和 Hudi 湖仓一体的大数据生态体系以及在 T3 的相关应用场景,内容包括:湖仓一体的架构 Flink/Hudi/Kylin 先容与交融 T3 出行结合湖仓一体的实践

一、湖仓一体的架构

数据湖和数据仓库

既然聊湖仓一体,我们先了解一下什么是湖,什么是仓。数据湖是一个很老的概念,在近些年又被热炒。业界对于数据湖到现在也没有一个统一的定义。AWS 是最早在云上推出数据湖解决方案的云效劳提供商,在这里我们便引用 AWS 对数据湖的定义:“数据湖是一个集中式的保存库,允许保存任意结构的数据并且能将它应用于大数据处理,以及进行实时分析和机器学习等相关的应用场景。” 同样我们也借助于 AWS 对数据仓库做这样的定义:“数据仓库是信息的一个中央保存库。” 这里的信息是可对其进行分析,并且可做出更明智的决策。

这个定义还有详细的展开。AWS 这张图通过展示了从湖到仓的数据流向的关系,来演示数据湖与数据仓库之间的区别和联系。首先数据最初是存在于数据湖或是数据库中,然后经过数据筛选和准备之后,就会流向数据仓库来进行一些高价值的分析。这个对比表格很直观的从数据、Schema、性价比、数据质量、用户和分析这 6 个维度给出数据湖和仓的对比。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

湖仓一体的先例

今年我们听说阿里巴巴提及的“湖仓一体”的概念。不知道大家有没有想过湖仓一体在业界是否有成功的先例?我个人认为是有的。今年 (2020年)9 月份,一家叫 Snowflake 的公司在纽交所上市。Snowflake 是一家做云数仓的公司,基于云厂商提供的基础设施提供 SaaS 平台,面向中小企业提供数据的托管和分析效劳。Snowflake 自称自己是一家云数仓公司,并且在 16 年的数据顶会上发表了一篇论文来先容他们弹性数仓的架构以及一些技术的细节。

Snowflake 其实是基于云上的对象保存,一份保存多份算计,并且算计与保存分离的这样一套架构。其实这就是 AWS 以及现在主流云厂商所主推的这个数据湖的架构。Snowflake上市的首日,他的市值就飙升到了 700 亿美元的规模。所以我个人认为 Snowflake 可以算是实行湖仓一体的一个最成功的先例。大家可以去了解一下刚谈到的这篇论文。我摘出了这 5 个点来和大家做简单的分享:

首先第一点,是没有走现在传统数仓所广泛应用的 Shared-Nothing 这个架构,而是转向 Shared-Data 这个架构。其次,论文中重点提及的保存和算计分离,是文中我觉得最有价值的一个观点。他提出了统一保存然后弹性算计的这样一个观念。第三,数仓及效劳是我认为他们商业化最成功的点。它将数仓提供了一个 SaaS 化的体验,并且摒弃传统上大家认为的数仓是大而重的偏见。第四,高可用这一块是提高用户体验和容错的很关键的一个点。最后,结构化延伸到半结构化这一块已经体现当时他们能够探索湖上通用数据的能力。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

这虽然是 16 年的一篇论文,但里面的观念并不算陈旧并且仍然值得我们去学习。后续我们会简单先容几个被我们吸收并且将会去实践的一些点,而且这些点也是 T3 出行在实现湖仓一体上很关键的地方。

Shared – Nothing 架构的优势

首先,作为一个被很多传统的数仓广泛应用的一个架构,Shared-Nothing 还是有一些架构上的优势:

第一点,Table 上的数据可以进行跨节点的水平分区,并且每个节点有自己的本地保存。每个节点的算计资源,只关注处理每个节点自己保存的数据。所以它的另一个优点就是它的处理机制相对简单,是数仓领域很典型的一个架构。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

Shared – Nothing 架构的劣势

这套架构其实也有一些不足的地方:

最大的一点就是他耦合了算计与保存资源,同时也带来第二个问题,就是弹性不足。具体可以体现在 2 个方面。a、集群在扩缩容的时候,数据需要被大量重分布b、没有办法简单地卸载不用的算计资源第三个问题是,耦合算计和保存资源同时也就造成了它的可用性是相当有限的。由于这些称之为有状态的算计,所以在失败或者是升级的时候会显著影响性能,并会导致效劳整体不可用的状态。最后是同构的资源与异构的负载的问题。因为在数仓的场景中,我们有很多异构的负载,比如说批量的加载,查问,报表的大规模算计分析等等。但 Shared-Nothing 架构的资源是同构的,所以这带来两者之间的碰撞。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

Shared – Data 架构

基于这些问题,Snowflake 提出了一个叫做 Multi-Cluster Shared-Data 架构。这里我们对官方的图做了一个简单的微调。

这个架构的第一个优势是它没有数据孤岛,是一个统一的保存。这也就能够将保存从算计中进行解耦。第二个优势是基于现在的对象保存去容纳结构化和非结构化数据。第三,它的集群规模是可以弹性作用的。第四,上述特征同时也带来了按需算计这个低成本优点。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

接下来我们以分层的形式来 review 这个架构。从整体上来看,它的结构大致分为三个层次。

最底层是云厂商提供的对象保存,也就是用户的保存。中间层是多用途多份的算计集群。再往上是数据湖的管理效劳,它存载的是一个大的 SaaS 化的平台,是对整个底层保存以及算计集群的管理的角色。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

Shared – Data 的持续高可用

接下来一个点是这个架构的高可用。这里可以简单分解为 2 个方面。第一个是失败容错,第二个是在线升级。

首先,作为一个 SaaS 化的应用,它的容错性是需要体现在整体架构上。这里我们同样分层来回顾一下。

最底层的保存层利用了云厂商的对象保存能力,他本身是一个跨中心复制以及接近无限扩容的一个机制,所以用户基本无需关心。再往上是多元的算计集群。每个算计集群是在同一个数据中心内,来保证它网络传输的性能。这里就提到一个问题,有可能某一个算计集群会有节点失败的问题。假如在一次查问中有一个节点失败,这些算计节点会将这个状态返回上面的效劳层。效劳层在接受这个失败后,会将这个算计再次传递到可用的节点中进行二次查问。所以 Shared-Data 保存和算计分离的这种架构上节点近乎是无状态的算计。这种架构的一个节点失败就不是一个非常大的问题。再往上效劳层对于元数据的保存也是利用了对象保存的这个能力。所以这个效劳层基本上可以看做是无状态的效劳。最上层是一个负载均衡器,可以进行效劳的冗余和负载的均摊。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

第二点在线升级这一块主要利用两个设计,其实这也并不是很新颖的做法。一个是在算计层和效劳层的多方面的映射,然后灰度的切换。这里可以看到在算计层是分多版本的,并且这些版本之间会共享本地的 Cache。效劳层的元数据管理也是在多方面共享。这其实也是架构内的子 Shared-Data,对于多版本之间的数据共享能做到再升级和平滑灰度的能力。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

接下来我的同事(王祥虎)会跟大家先容这 3 个框架以及它们是如何交融并最终支撑 T3 湖仓一体的实践。在先容第二个议题前他会先先容我们的主框架,Hudi 和 Kylin 框架,然后再先容他们三者之间是如何两两交融。最后再先容T3是如何构建湖仓一体的。

二、Flink/Hudi/Kylin 先容与交融

Hudi

首先来了解一下 Hudi 是什么。Hudi 最初是由 Uber 的工程师为了满足他们的数据分析需求设计开发的一个数据湖框架。它于 2019 年 1 月份加入到 Apache 孵化器,并于 2020 年 5 月顺利毕业,成为 Apache 的顶级项目。Hudi 的名字来源于 Hadoop Upserts Deletes and Incrementals 的缩写。也就是说,Hudi 是一个支撑插入、革新、删除、以及增量处理的数据湖框架。除此之外,它还支撑事务性 ACID 增量处理、保存管理和时间管理。Hudi 能够管理云上超大规模上百 PB 的分析型数据集,对于所有的云效劳都开箱即用,非常的方便,而且已经在 Uber 内部稳定运行了接近 4 年。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

下图是 Hudi 的插件化架构。我们可以看到,Hudi 在保存、数据处理引擎、表类型、索引类型、查问视图和查问引擎方面都有比较宽松的支撑。也就是说,他不与某一个组件绑定。

在保存方面,Hudi 可以支撑 HDFS,OSS 和 S3。在数据处理引擎方面,Hudi 支撑 Flink 和 Spark。Java 和 Python 客户端已经在社区支撑中。Hudi 支撑两种表,COW 和 MOR,这两种表分别对应低延迟的查问和快速摄入两种场景。在索引方面,Hudi 支撑 Bloom 和 HBase 等 4 种索引类型。底层用了 Parquet 和 Avro 保存数据,社区还正在做 ORC 格式的支撑以及 SQL支撑,相信不久的将来会跟大家见面。

Hudi 支撑 3 种查问,读优化查问,增量查问和快照查问。而在查问引擎方面,有 Spark 、Presto、Hive 和 Impala,实际上一些其他的组件已经支撑了。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

下面详细的先容一下保存模式和视图。

第一个是 Copy On Write 模式,对应到 Hudi 的 COW 表。它是一种侧重低延时的数据查问场景的表,底层应用 Parquet 数据文件保存数据,能够支撑快照查问和增量查问两种查问方式。在查问引擎方面,大家可以看到上面有 5 个引擎,他们对快照查问、增量查问和读优化 3 种视图都有不同程度的支撑。Merge On Read 表对 Copy On Write 有不同层面的互补,可以看到它侧重于快速的数据摄入场景。应用 Parquet 文件来保存具体的数据,应用行式 Avro 增量文件来保存操作日志,类似于 HBase WAL。它支撑 Hudi 所有 3 种视图,可以看到 Hive,Spark SQL,Spark Datasource, Presto 和 Impala 对于读优化查问都是支撑的。而 Hive, Spark SQL 只支撑到了快照查问。这种组件支撑的信息大家以后可以到官网上查问。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

在出行业务中,订单会有支付长尾的属性。也就是说一个订单开始之后,它的支付环节可能会拖的比较久。换言之,它可能会在这个用户下一次出行前才进行支付(也或许会更久,甚至永远不支付)。这种长尾属性将会导致一个超长的业务闭环窗口,会导致我们无法准确预测数据的革新时机。如果存在多级革新的话,链路会比较长,革新成本也非常的高。

下图是我们的长尾革新引发的冷数据频繁革新示意图。左侧是业务库,右侧是有依赖关系的 3 张示意表。当业务库有数据革新时,右侧需要革新的数据可能已经归档到性能相对较差的设备上,增加数据革新成本。而且如果这次数据革新会引发长链路级联革新的话,这种慢速的 I/O 还会被进一步放大。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

数据的可靠性也是数据 ETL 中不可避免的问题。可能由于机器故障或者算计逻辑导致加工处理的数据失真或者完全不对,就会给运营的决策造成很大的影响。数字延迟性方面,在基于 Hive 构件的传统架构中,由于 Hive 缺少索引机制,所以数据革新大都会导致数据分区重写,且没有办法原地删除。其次小文件问题会增加 NameNode 保存和查问的负担,拖慢进程,在一定程度上增加数据延迟性。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

Kylin 框架

我们再来先容一下这个 Kylin 框架。相比较 Hudi,大家应该会对 Kylin 相对熟悉一些,它是一个开源的分布式分析型数据仓库,能够提供 Hadoop/Spark SQL 之上的数据查问窗口。最初是由 eBay 开放并贡献到开源社区,能够在亚秒内查问巨大的表。它的秘诀其实就是做预算计,针对一个星型拓扑结构数据立方体,预算多个维度组合的度量把结果写出到输出表,对外暴露查问接口实现实时查问,也就是用空间来换取存取时间。

Kylin 在今年的 9 月份发布了 4.0 alpha 版本,这是在 Kylin3 之后一个重大架构升级。应用 Parquet 代替 Hbase 保存,从而提升了文件的扫描性能,也减轻甚至消除了 Hbase 的维护负担。Kylin4 重新实现 Spark 构建引擎和查问引擎,使得算计和保存分离,也更加适用云原生的技术趋势。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

Flink/Hudi/Kylin 框架之间的交融

伴随 Kylin3.1 发布,Kylin 与 Flink 就交融已经完成。这个特性是在 2019 年完成的,Kylin 与 Flink 的集成开始于去年 1 月,通过 Flink Batch 实现。关于 Hudi 交融,可以说 Kylin 和 Hudi 天生就是兼容的,因为 Hudi 可以将自己暴露成一张 Hive 表,用户可以像读取 Hive 一样应用 Hudi 的数据,这样对Kylin会非常友好。因为 Kylin 可以把 Hudi 当成一张 Hive 表无缝应用数据。Hudi 和 Flink 交融这个特性是我今年对社区的主要贡献。这个两张截图对应 Hudi 和 Flink 交融路上的2个里程碑式的PR。

第一个 Hudi client 支撑多引擎,将 Hudi 与 Spark 解耦,让 Hudi 支撑多引擎成为可能。第二个是 Flink 客户端基本实现贡献到社区,让 Hudi 可以真正意义上写入 Flink 数据表。这 2 个改动非常大,加在一起已经超过了 1 万行的代码,也可以说是今年 Hudi 社区比较亮眼的一个特性。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

Hudi 和 Flink 的交融过程

下面来详细先容下 Hudi 和 Flink 交融过程。Hudi 原本只支撑 Spark 引擎,所以第一步是将 Hudi 与 Spark 解耦之后再去集成我们想要的引擎。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

解耦的难点在于 Hudi 最初没有考虑多引擎的支撑,所以从数据源读取数据到最终将数据写出到 Hudi 表,RDD 无处不在。连普通的工具类都会应用 RDD 作为基本的操作单元。与 Spark 解耦,我们评估到他的改动非常的大。其次是 Flink 与 Spark 核心笼统上的差异。Spark 认为数据是有限的数据集,而 Flink 认为数据是无界的,是一种数据流。这种笼统上的差异导致我们很难统一出一个通用的笼统。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

这次改动对于 Hudi 来说是伤筋动骨的,因此我们决定要优先保证原版 Hudi 的功能和性能,当然也牺牲了部分 Flink Stream API。让 Flink 来操作 list,而用Spark 操作 RDD。这样就可以抽取一个泛型出来形成一个统一的笼统层。

笼统原则:

统一应用泛型 I、K、O 代替。去 Spark 化,笼统层 API 都是引擎无关的,难以在笼统层实现的,我们会把它改为笼统方法下推到 Spark 子类实现。不影响原版,笼统层尽量的减少改动,以保证固定的功能性。引入 HoodieEngineContext 代替 JavaSparkContext, 提供运行时的上下文。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

下面说 Flink Client DAG,这里主要分了 5 部分,

第一部分是 Kafka Streaming Source,主要用来接收Kafka数据并转换成 List。第二个是 InstantGeneratorOperator,一个 Flink 算子, 用来生成全局唯一的 instant。第三是 KeyBy 分区操作,根据 partitionPath 分区避免多个子任务将数据写入同一个分区造成冲突。第四个是 WriteProcessOperator,这也是我们自定义的一个算子。这个算子是写操作实际发生的地方。第五个是 CommitSink,他会接受上游 WriteProcessOperator 发来的数据,根据上游数据判断是否提交事务。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

下面是 Flink 革新的代码示例。左侧是原版里面 HoodieWriteClient 简化的版本,可以看到 insert 函数的入参是 RDD,返回值也是 RDD。右侧笼统之后的 abstract 可以看到它的入参变成了泛型I,返回值变成了 O,有兴趣的话大家可以去了解一下。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

下面是我们对 Flink 如何交融的另外一个想法,就是希望做出一个 streaming source,应用 Flink 构建一个完整的从 Hudi 表读数据,再写出到 Hudi 表的 ETL 管道。

然后是我们初步的设想。左侧灰色的图里面有 5 列的 Hudi 元数据。最左侧是 hoodie_commit_time 事务列表。每一个 hoodie_commit_time 对应一个事务,每一个事务对应一批的数据。每一批数据中的每一条记录都会有一个提交的序列号,就是第 2 列 hoodie_commit_seqno 序列号。hoodie_commit_time 和 hoodie_commit_seqno 这种映射关系跟 Kafka 中的分区和 offset 的这种映射关系非常类似。后期我们可能会基于这种特点实现一个 Hoodie Streaming Source。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

基于这 3 个框架之间的交融关系,我们发现分别用于算计、分析、保存的这 3 个引擎之间是相互兼容的。并且他们能够支撑湖仓一体,向云原生体系靠拢。

三、T3 出行结构湖仓一体的实践

最后我们来看一看 T3 出行是如何构建湖仓一体的。这是我们 T3 出行车联网的架构,可以看到是从底向上,从基础支撑到上层不停的赋能,并与车企的信息系统、国家信息平台做交互。作为一家车联网驱动的出行公司,我们收集到了人、车、路等相关的数据,每一种数据都有它自己的应用场景, 数据之间并不孤立,相互赋能,共同支撑 T3 智慧出行。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

这是我们的保存和算计分离的数据库架构,整个架构分为了两层,一层是算计层,一层是保存层。

算计层我们用到了 Flink、Spark、Kylin 和 Presto 并且搭配 ES 做任务调度。数据分析和展示方面用到了达芬奇和 Zeppelin。在保存层,我们应用了阿里云 OSS 并搭配 HDFS 做数据保存。数据格式方面应用 Hudi 作为主要的保存格式,并配合 Parquet、ORC 和 Json 文件。在算计和保存之前,我们加了一个 Alluxio 来加速提升数据处理性能。资源管理方面我用到了 Yarn,在后期时机成熟的时候也会转向 K8s。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

在当前保存算计分离的趋势下,我们也是以湖保存为核心,在它周围构建了湖加速湖算计、OLAP 分析、交互式查问、可视化等等一整套的大数据生态体系。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

T3对 Hudi 的应用场景

下面是我们 T3 内部对 Hudi 的几个应用场景。

一个是近实时的流数据管道。我们可以从左侧通过 Log、MySQL 或者直接读取业务数据的 Kafka,把数据导入到数据管道中,再应用 Flink 或者原版的 DeltaStreamer 将流式数据输入到列表中。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

近实时的流式数据处理的 Flink UI 界面上可以看到之前先容的 DAG 的几个算子都在里面,比如 source、instant_generator 等。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

另一个是近实时的数据分析场景。我们应用 Hive、Spark 或 Presto 查问数据,并最终用达芬奇或者 Zeppelin 做最终的数据报表。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

这是我们用 Hudi 构建的增量数据管道。最左侧 CDC 数据捕获之后要革新到后面的一系列的表。有了 Hudi 之后,因为 Hudi 支撑索引和增量数据处理,我们只需要去革新需要革新的数据就可以了,不需要再像以前那样去革新整个分区或者革新整个表。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

最后的一个场景是将前面先容的用 Flink 将线上或者业务数据订阅 ETL 到 Hudi 表中供机器学习应用。但是机器学习是需要有数据基础的,所以我们利用 Hudi 将线上的数据增量发布到线下环境,进行模型训练或者调参。之后再将模型发布到线上为我们的业务提供效劳。

交融趋势下基于 Flink Kylin Hudi 湖仓一体的大数据生态体系

给TA打赏
共{{data.count}}人
人已打赏
AI

浙大校友李旻辰获SIGGRAPH 2021最佳博士论文奖,连续四年华人学者包揽此奖项

2021-8-10 14:41:00

AI

Hologres揭秘:深度解析高效率分布式盘问引擎

2021-8-11 15:09:00

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
今日签到
搜索