怎么实现Apache Hudi和Presto的原理分析

发布时间:2022-01-18 15:50:13 作者:柒染
来源:亿速云 阅读:202

今天给大家介绍一下怎么实现Apache Hudi和Presto的原理分析。文章的内容小编觉得不错,现在给大家分享一下,觉得有需要的朋友可以了解一下,希望对大家有所帮助,下面跟着小编的思路一起来阅读吧。


1. 概述

Apache Hudi 是一个快速迭代的数据湖存储系统,可以帮助企业构建和管理PB级数据湖,Hudi通过引入upsertsdeletes和增量查询等原语将流式能力带入了批处理。这些特性使得统一服务层可提供更快、更新鲜的数据。Hudi表可存储在Hadoop兼容的分布式文件系统或者云上对象存储中,并且很好的集成了 Presto, Apache Hive, Apache Spark 和Apache Impala。Hudi开创了一种新的模型(数据组织形式),该模型将文件写入到一个更受管理的存储层,该存储层可以与主流查询引擎进行互操作,同时在项目演变方面有了一些有趣的经验。

本博客讨论Presto和Hudi集成的演变,同时讨论Presto-Hudi查询即将到来的文件Listing和查询计划优化。

 

2. Apache Hudi

Apache Hudi(简称Hudi)提供在DFS上存储超大规模数据集,同时使得流式处理如果批处理一样,该实现主要是通过如下两个原语实现。

怎么实现Apache Hudi和Presto的原理分析

上图说明了Hudi的原语,配合这些原语可以直接在DFS抽象之上解锁流/增量处理功能。这和直接从Kafka Topic消费事件,然后使用状态存储来增量计算临时结果类似,该架构有很多优点。

 

2.1 Hudi表和查询类型

 
2.1.1 表类型

Hudi支持如下两种类型表

Copy On Write (COW): 使用列式存储格式(如parquet)存储数据,在写入时同步更新版本/重写数据。

Merge On Read (MOR): 使用列式存储格式(如parquet)+ 行存(如Avro)存储数据。更新被增量写入delta文件,后续会进行同步/异步压缩产生新的列式文件版本。

下表总结了两种表类型的trade-off。

Trade-offCopyOnWriteMergeOnRead
数据延迟更高更低
更新开销 (I/O)高(重写整个parquet文件)更低 (写入增量日志文件)
Parquet文件大小更小(高update (I/0) 开销)更大 (低updaet开销)
写放大更低 (决定与Compaction策略)
 
2.1.2 查询类型

Hudi支持如下查询类型

快照查询: 查询给定commit/compaction的表的最新快照。对于Merge-On-Read表,通过合并基础文件和增量文件来提供近实时数据(分钟级);对于Copy-On-Write表,对现有Parquet表提供了一个可插拔替换,同时提供了upsert/delete和其他特性。

增量查询: 查询给定commit/compaction之后新写入的数据,可为增量管道提供变更流。

读优化查询: 查询给定commit/compaction的表的最新快照。只提供最新版本的基础/列式数据文件,并可保证与非Hudi表相同的列式查询性能。

下表总结了不同查询类型之间的trade-off。

Trade-off快照读优化
数据延迟更低更高
查询延迟COW: 与parquet表相同。MOR: 更高 (合并基础/列式文件和行存增量文件)与COW快照查询有相同列式查询性能

下面动画简单演示了插入/更新如何存储在COW和MOR表中的步骤,以及沿着时间轴的查询结果。其中X轴表示每个查询类型的时间轴和查询结果。

怎么实现Apache Hudi和Presto的原理分析

注意,作为写操作的一部分,表的commit被完全合并到表中。对于更新,包含该记录的文件将使用所有已更改记录的新值重新写入。对于插入,优先会将记录写入到每个分区路径中最小文件,直到它达到配置的最大大小。其他剩余的记录都将写入新的文件id组中,会保证再次满足大小要求。

怎么实现Apache Hudi和Presto的原理分析


 

MOR和COW在摄取数据方面经历了相同步骤。更新将写入属于最新文件版本的最新日志(delta)文件,而不进行合并。对于插入,Hudi支持2种模式:

增量日志文件后面通过时间轴中的压缩(compaction)操作与基础parquet文件合并。这种表类型是最通用、高度高级的,为写入提供很大灵活性(指定不同的压缩策略、处理突发性写入流量等)和查询提供灵活性(例如权衡数据新鲜度和查询性能)。

 

3. Presto

 

3.1 早期Presto集成方案

Hudi设计于2016年中后期。那时我们就着手与Hadoop生态系统中的查询引擎集成。为了在Presto中实现这一点,正如社区建议的那样,我们引入了一个自定义注解@UseFileSplitsFromInputFormat。任何注册的Hive表(如果有此注解)都将通过调用相应的inputformat的getSplits()方法(而不是Presto Hive原生切片加载逻辑)来获取切片。通过Presto查询的Hudi表,只需简单调用HoodieParquetInputFormat.getSplits(). 集成非常简单只,需将相应的Hudi jar包放到<presto_install>/plugin/hive-hadoop2/目录下。它支持查询COW Hudi表,并读取MOR Hudi表的优化查询(只从压缩的基本parquet文件中获取数据)。在Uber,这种简单的集成已经支持每天超过100000次的Presto查询,这些查询来自使用Hudi管理的HDFS中的100PB的数据(原始数据和模型表)。

 

3.2 移除InputFormat.getSplits()

调用inputformat.getSplits()是个简单的集成,但是可能会导致对NameNode的大量RPC调用,以前的集成方法有几个缺点。

我们开始重新思考Presto-Hudi的整合方案。在Uber,我们通过在Hudi上添加一个编译时依赖项来改变这个实现,并在BackgroundHiveSplitLoader构造函数中实例化HoodieTableMetadata一次。然后我们利用Hudi Api过滤分区文件,而不是调用HoodieParquetInputFormat.getSplits(),这大大减少了该路径中NameNode调用次数。

为了推广这种方法并使其可用于Presto-Hudi社区,我们在Presto的DirectoryLister接口中添加了一个新的API,它将接受PathFilter对象。对于Hudi表,我们提供了这个PathFilter对象HoodieROTablePathFilter,它将负责过滤为查询Hudi表而预先列出的文件,并获得与Uber内部解决方案相同的结果。

这一变化是从0.233版本的Presto开始提供,依赖Hudi版本为0.5.1-incubating。由于Hudi现在是一个编译时依赖项,因此不再需要在plugin目录中提供Hudi jar文件。

 

3.3 Presto支持查询Hudi MOR表

我们看到社区有越来越多人对使用Presto支持Hudi MOR表的快照查询感兴趣。之前Presto只支持查询Hudi表读优化查询(纯列式数据)。随着该PR https://github.com/prestodb/presto/pull/14795被合入,现在Presto(0.240及后面版本)已经支持查询MOR表的快照查询,这将通过在读取时合并基本文件(parquet数据)和日志文件(avro数据)使更新鲜的数据可用于查询。

在Hive中,这可以通过引入一个单独的InputFormat类来实现,该类提供了处理切片的方法,并引入了一个新的RecordReader类,该类可以扫描切片以获取记录。对于使用Hive查询MOR Hudi表,在Hudi中已经有类似类可用:

为了让Hudi实时查询正常工作,我们确定并进行了以下必要更改:

有了这些变更,Presto用户便可查询Hudi MOR表中更新鲜的数据了。

 

4. 下一步计划

下面是一些很有意思的工作(RFCs),可能也需要在Presto中支持。

RFC-12: Bootstrapping Hudi tables efficiently

ApacheHudi维护每个记录的元数据,使我们能够提供记录级别的更新、唯一的键语义和类似数据库的更改流。然而这意味着,要利用Hudi的upsert和增量处理能力,用户需要重写整个数据集,使其成为Hudi表。这个RFC提供了一种机制来高效地迁移他们的数据集,而不需要重写整个数据集,同时还提供了Hudi的全部功能。

这将通过在新的引导Hudi表中引用外部数据文件(来自源表)的机制来实现。由于数据可能驻留在外部位置(引导数据)或Hudi表的basepath(最近的数据)下,FileSplits将需要在这些位置上存储更多的元数据。这项工作还将利用并建立在我们当前添加的Presto MOR查询支持之上。

支持Hudi表增量和时间点时间旅行查询

增量查询允许我们从源Hudi表中提取变更日志。时间点查询允许在时间T1和T2之间获取Hudi表的状态。这些已经在Hive和Spark中得到支持。我们也在考虑在Presto中支持这个特性。

在Hive中,通过在JobConf中设置一些配置来支持增量查询,例如-query mode设置为INCREMENTAL、启动提交时间和要使用的最大提交数。在Spark中有一个特定的实现来支持增量查询—IncrementalRelation。为了在Presto中支持这一点,我们需要一种识别增量查询的方法。如果Presto不向hadoop Configuration对象传递会话配置,那么最初的想法是在metastore中将同一个表注册为增量表。然后使用查询谓词获取其他详细信息,如开始提交时间、最大提交时间等。

RFC-15: 查询计划和Listing优化

Hudi write client和Hudi查询需要对文件系统执行listStatus操作以获得文件系统的当前视图。在Uber,HDFS基础设施为Listing做了大量优化,但对于包含数千个分区的大型数据集以及每个分区在云/对象存储上有数千个文件的大型数据集来说,这可能是一个昂贵的操作。上面的RFC工作旨在消除Listing操作,提供更好的查询性能和更快的查找,只需将Hudi的时间轴元数据逐渐压缩到表状态的快照中。

该方案旨在解决:

为此,Presto也需要一些变更。我们正在积极探索在查询规划阶段利用这些元数据的方法。这将是对Presto-Hudi集成的重要补充,并将进一步降低查询延迟。

记录级别索引

Upsert是Hudi表上一种流行的写操作,它依赖于索引将传入记录标记为Upsert。HoodieIndex在分区或非分区数据集中提供记录id到文件id的映射,实现有BloomFilters/Key ranges(用于临时数据)和Apache HBase(用于随机更新)支持。许多用户发现Apache HBase(或任何类似的key-value-store-backed索引)很昂贵,并且增加了运维开销。该工作试图提出一种新的索引格式,用于记录级别的索引,这是在Hudi中实现的。Hudi将存储和维护记录级索引(有HFile、RocksDB等可插拔存储实现支持)。这将被writer(摄取)和reader(摄取/查询)使用,并将显著提高upsert性能,而不是基于join的方法,或者是用于支持随机更新工作负载的布隆索引。这是查询引擎在列出文件之前修剪文件时可以利用这些信息的另一个领域。我们也在考虑一种在查询时利用Presto中的元数据的方法。

    

以上就是怎么实现Apache Hudi和Presto的原理分析的全部内容了,更多与怎么实现Apache Hudi和Presto的原理分析相关的内容可以搜索亿速云之前的文章或者浏览下面的文章进行学习哈!相信小编会给大家增添更多知识,希望大家能够支持一下亿速云!

推荐阅读:
  1. Apache四个大型开源数据和数据湖系统是什么
  2. 如何使用Apache Pulsar + Hudi 构建 Lakehouse

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

apache hudi presto

上一篇:怎么用Python装饰器来缓存函数的返回值

下一篇:怎么用Python编写一个拼写纠错器

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》