常见的三大数据湖技术Delta、Hudi、Iceberg对比
一、Delta、Hudi、Iceberg对比概览
由于Apache Spark在商业化上取得巨大成功,所以由其背后商业公司Databricks推出的Delta lake也显得格外亮眼。在没有delta数据湖之前,Databricks的客户一般会采用经典的lambda架构来构建他们的流批处理场景。
Apache Hudi是由Uber的工程师为满足其内部数据分析的需求而设计的数据湖项目,它提供的fast upsert/delete以及compaction等功能可以说是精准命中广大人民群众的痛点,加上项目各成员积极地社区建设,包括技术细节分享、国内社区推广等等,也在逐步地吸引潜在用户的目光。
Netflix的数据湖原先是借助Hive来构建,但发现Hive在设计上的诸多缺陷之后,开始转为自研Iceberg,并最终演化成Apache下一个高度抽象通用的开源数据湖方案。
Apache Iceberg目前看则会显得相对平庸一些,简单说社区关注度暂时比不上delta,功能也不如Hudi丰富,但却是一个野心勃勃的项目,因为它具有高度抽象和非常优雅的设计,为成为一个通用的数据湖方案奠定了良好基础。
二、共同点
三者均为Data Lake的数据存储中间层,其数据管理的功能均是基于一系列的meta文件。Meta文件的角色类似于数据库的catalog\wal,起到schema管理、事务管理和数据管理的功能。与数据库不同的是,这些meta文件是与数据文件一起存放在存储引擎中的,用户可以直接看到。这个做法直接继承了大数据分析中数据对用户可见的传统,但是无形中也增加了数据被不小心破坏的风险。一旦删了meta目录,表就被破坏了,恢复难度很大。
Meta包含有表的schema信息。因此系统可以自己掌握schema的变动,提供schema演化的支持。Meta文件也有transaction log的功能(需要文件系统有原子性和一致性的支持)。所有对表的变更都会生成一份新的meta文件,于是系统就有了ACID和多版本的支持,同时可以提供访问历史的功能。在这些方面,三者是相同的。
三、关于Hudi
Hudi 的设计目标正如其名,Hadoop Upserts Deletes and Incrementals(原为 Hadoop Upserts anD Incrementals),强调了其主要支持 Upserts、Deletes 和 Incremental 数据处理,其主要提供的写入工具是 Spark HudiDataSource API 和自身提供的 HoodieDeltaStreamer,均支持三种数据写入方式:UPSERT,INSERT 和 BULK_INSERT。其对 Delete 的支持也是通过写入时指定一定的选项支持的,并不支持纯粹的 delete 接口。
在查询方面,Hudi 支持 Hive、Spark、Presto。
在性能方面,Hudi 设计了 HoodieKey ,一个类似于主键的东西。对于查询性能,一般需求是根据查询谓词生成过滤条件下推至 datasource。Hudi 这方面没怎么做工作,其性能完全基于引擎自带的谓词下推和 partition prune 功能。
Hudi 的另一大特色是支持 Copy On Write 和 Merge On Read。前者在写入时做数据的 merge,写入性能略差,但是读性能更高一些。后者读的时候做 merge,读性能差,但是写入数据会比较及时,因而后者可以提供近实时的数据分析能力。 最后,Hudi 提供了一个名为 run_sync_tool 的脚本同步数据的 schema 到 Hive 表。Hudi 还提供了一个命令行工具用于管理 Hudi 表。
四、关于Iceberg
Iceberg 没有类似的 HoodieKey 设计,其不强调主键。上文已经说到,没有主键,做 update/delete/merge 等操作就要通过 Join 来实现,而 Join 需要有一个 类似 SQL 的执行引擎。
在查询方面,Iceberg 支持hive、 Spark、Presto。
Iceberg 在查询性能方面做了大量的工作。值得一提的是它的 hidden partition 功能。Hidden partition 意思是说,对于用户输入的数据,用户可以选取其中某些列做适当的变换(Transform)形成一个新的列作为 partition 列。这个 partition 列仅仅为了将数据进行分区,并不直接体现在表的 schema 中。
除了 hidden partition,Iceberg 也对普通的 column 列做了信息收集。这些统计信息非常全,包括列的 size,列的 value count,null value count,以及列的最大最小值等等。这些信息都可以用来在查询时过滤数据。
Iceberg 提供了建表的 API,用户可以使用该 API 指定表名、schema、partition 信息等,然后在 Hive catalog 中完成建表。
五、关于Delta
Delta 的定位是流批一体的 Data Lake 存储层,支持 update/delete/merge。由于出自 Databricks,spark 的所有数据写入方式,包括基于 dataframe 的批式、流式,以及 SQL 的 Insert、Insert Overwrite 等都是支持的(开源的 SQL 写暂不支持,EMR 做了支持)。不强调主键,因此其 update/delete/merge 的实现均是基于 spark 的 join 功能。在数据写入方面,Delta 与 Spark 是强绑定的,这一点 Hudi 是不同的:Hudi 的数据写入不绑定 Spark(可以用 Spark,也可以使用 Hudi 自己的写入工具写入)。
在查询方面,开源 Delta 目前支持 Spark 与 Presto,但是,Spark 是不可或缺的,因为 delta log 的处理需要用到 Spark。这意味着如果要用 Presto 查询 Delta,查询时还要跑一个 Spark 作业。更为蛋疼的是,Presto 查询是基于 SymlinkTextInputFormat 。在查询之前,要运行 Spark 作业生成这么个 Symlink 文件。如果表数据是实时更新的,意味着每次在查询之前先要跑一个 SparkSQL,再跑 Presto。为此,EMR 在这方面做了改进可以不必事先启动一个 Spark 任务。
在查询性能方面,开源的 Delta 几乎没有任何优化。
Delta 在数据 merge 方面性能不如 Hudi,在查询方面性能不如 Iceberg,是不是意味着 Delta 一无是处了呢?其实不然。Delta 的一大优点就是与 Spark 的整合能力,尤其是其流批一体的设计,配合 multi-hop 的 data pipeline,可以支持分析、Machine learning、CDC 等多种场景。使用灵活、场景支持完善是它相比 Hudi 和 Iceberg 的最大优点。另外,Delta 号称是 Lambda 架构、Kappa 架构的改进版,无需关心流批,无需关心架构。这一点上 Hudi 和 Iceberg 是力所不及的。
六、总结
三个引擎的初衷场景并不完全相同,Hudi 为了 incremental 的 upserts,Iceberg 定位于高性能的分析与可靠的数据管理,
Delta 定位于流批一体的数据处理。这种场景的不同也造成了三者在设计上的差别。尤其是 Hudi,其设计与另外两个相比差别
更为明显。 因此后面是趋同还筑起各自专长优势壁垒未可知。
Delta、Hudi、Iceberg三个开源项目中,Delta和Hudi跟Spark的代码深度绑定,尤其是写入路径。这两个项目设计之初,
都基本上把Spark作为他们的默认计算引擎了。而Apache Iceberg的方向非常坚定,宗旨就是要做一个通用化设计的Table Format。
它完美的解耦了计算引擎和底下的存储系统,便于多样化计算引擎和文件格式,很好的完成了数据湖架构中的Table Format
这一层的实现,因此也更容易 成为Table Format层的开源事实标准。
另一方面,Apache Iceberg也在朝着流批一体的数据存储层发展,manifest和snapshot的设计,有效地隔离不同transaction
的变更 ,非常方便批处理和增量计算。并且,Apache Flink已经是一个流批一体的计算引擎,二都可以完美匹配,合力打造
流批一体的数据湖架构。
最后,Apache Iceberg这个项目背后的社区资源非常丰富。在国外,Netflix、Apple、Linkedin、Adobe等公司都有PB级别的
生产数据运行在Apache Iceberg上;在国内,腾讯这样的巨头也有非常庞大的数据跑在Apache Iceberg之上,最大的业务每天有
几十T的增量数据写入。社区成员同样非常资源和多样化,拥有来自其他项目的7位ApachePMC , 1为VP。体现在代码和设计
的review上,就变得非常苛刻,一个稍微大一点的PR涉及100+的comment很常见。这些都使得Apache Iceberg的设计+代码质量比较高。
Apache Iceberg 0.10.0 版本的发布,已经拉开集成 Flink 和 Iceberg 的序幕。
基于以上,个人比较推荐选择Apache Iceberg,并且建议和Apark Flink搭配。