从确保准确的ETA到预测最优交通路线,在优步平台上提供安全、无缝的运输和交付体验需要可靠、高性能的大规模数据存储和分析。2016年,优步开发了增量处理框架Apache Hudi,为业务关键数据管道提供低延迟、高效率的动力。一年后,我们选择将解决方案开源,以允许其他依赖数据的组织利用其优势,然后在2019年,我们将这一承诺更进一步,将其捐赠给Apache软件基金会。现在,将近一年半过去了,Apache Hudi已经毕业于Apache软件基金会的顶级项目。在我们纪念这一里程碑之际,我们想分享我们构建、发布、优化和毕业Apache Hudi的历程,以造福于更大的大数据社区。
Apache Hudi是一个存储抽象框架,可帮助分布式组织构建和管理PB级的数据湖。使用upserts和增量拉取等原语,Hudi将流样式处理带入了类似批处理的大数据。这些功能通过一个数据延迟在几分钟数量级的统一服务层,帮助我们的服务更快、更新地显示数据,避免了维护多个系统的任何额外开销。除了灵活性,Apache Hudi还可以在Hadoop分布式文件系统(HDFS)或云存储上运行。
Hudi支持数据湖上的原子性、一致性、隔离性和持久性(ACID)语义。Hudi最广泛使用的两个特性是Upserts和Incremental Pull,这两个特性使用户能够吸收变化数据捕获并将其大规模应用到数据湖中。为了实现这一点,HUDI提供了广泛的可插拔索引功能,以及它自己的数据索引实现。Hudi能够控制和管理数据湖中的文件布局,这不仅对于克服HDFS NameNode和其他云存储的限制极其重要,而且对于通过提高可靠性和查询性能来维护健康的数据生态系统也是极其重要的。为此,Hudi支持多种查询引擎集成,如Presto、Apache Have、Apache Spark和Apache Impala。
从高层次上讲,Hudi在概念上分为3个主要组件:需要存储的原始数据、用于提供upsert功能的数据索引和用于管理数据集的元数据。Hudi的核心是维护在不同时间点在桌面上执行的所有操作的时间表,称为Hudi中的瞬间。这提供了表格的即时视图,同时还有效地支持按到达顺序检索数据。Hudi保证在时间线上执行的操作是原子的,并且基于即时时间,换言之,即在数据库中进行更改的时间。有了这些信息,Hudi提供了同一HUDI表的不同视图,包括用于快速列性能的读取优化视图、用于快速数据获取的实时视图,以及用于将HUDI表作为更改日志流读取的增量视图,如上图1所示。
HUDI将数据表组织到分布式文件系统上的基本路径下的目录结构中。表被划分为多个分区,在每个分区内,文件被组织成由文件ID唯一标识的文件组。每个文件组包含多个文件切片,其中每个切片包含在特定提交/压缩瞬间生成的基本文件(*.parquet),以及一组日志文件(*.log.*),这些日志文件包含自生成基本文件以来对基本文件的插入/更新。HUDI采用多版本并发控制(MVCC),其中压缩合并日志和基础文件以产生新的文件切片,清理动作去除未使用的/较旧的文件切片以回收文件系统上的空间。
HUDI支持两种表类型:写入时复制和读取时合并。写入时复制表格类型仅使用列式文件格式(例如Apache Parquet)存储数据。通过写入时复制,通过在写入期间执行同步合并,可以简单地更新文件的版本并重写文件。
读取时合并表格类型使用列(例如,Apache parquet)和基于行(例如,Apache Avro)文件格式的组合来存储数据。更新被记录到增量文件中,稍后被压缩以同步或异步地生成新版本的列文件。
HUDI还支持两种查询类型:快照查询和增量查询。快照查询是获取给定提交或压缩操作的表的“快照”的请求。在利用快照查询时,写时拷贝表类型仅公开最新文件片段中的基本/列文件,并保证与非HUDI列表相比具有相同的列查询性能。写入时复制可替代现有镶木镶嵌桌,同时提供向上插入/删除等功能
在优步,我们利用Hudi进行各种使用案例,从在优步平台上提供快速、准确的出行数据,从检测欺诈到在我们的UberEats平台上提供餐厅和食物推荐。为了演示Hudi是如何工作的,让我们来看看我们如何确保Uber Marketplace中的出行数据在数据湖上是新鲜和最新的,从而改善Uber平台上乘客和司机的用户体验。旅行的典型生命周期从骑手请求旅行时开始,随着旅行的进行而继续,在旅行结束并且骑手到达他们的最终目的地时结束。优步的核心出行数据以表格的形式存储在优步的可伸缩数据存储Schemaless中。Trips表中的单个Trips条目可以在Trips的生命周期中经历多次更新。在Uber实现Hudi之前,大型Apache Spark作业定期将整个数据集重写到Apache HDFS,以吸收上游在线表插入、更新和删除,从而反映出行状态的变化。作为背景,在2016年初(在我们构建Hudi之前),我们的一些最大的工作使用了1000多个执行器,处理了超过20TB的数据。这一过程不仅效率低下,而且更难规模化。整个公司的各个团队都依赖快速、准确的数据分析来提供高质量的用户体验,为了满足这些要求,我们当前的解决方案显然无法扩展以促进数据湖的增量处理。使用快照和重载解决方案将数据移动到HDFS时,这些低效会泄漏到所有管道,包括使用这些原始数据的下游ETL。我们可以看到,这些问题只会随着规模的扩大而加剧。
在没有其他可行的开源解决方案可供使用的情况下,我们在2016年末为优步构建并推出了Hudi,以构建一个事务性数据湖,促进大规模快速、可靠的数据更新。优步的第一代Hudi独家利用了写时拷贝表类型,将作业处理速度提高到了每30分钟20 GB,将I/O和写入放大减少了100倍。截至2017年底,优步的所有原始数据表都利用了Hudi格式,运行着地球上最大的交易数据湖之一。
随着优步数据处理和存储需求的增长,我们开始遇到胡迪写时拷贝功能的限制,主要是需要继续提高数据的显示速度和新鲜度。即使使用Hudi的写入时复制功能,我们的一些表也收到了分布在90%的文件中的更新,导致数据湖中任何给定的大型表的数据重写都在100 TB左右。由于即使是针对单个修改的记录,重写时拷贝也会重写整个文件,因此写入时拷贝功能会导致高度的写入放大和降低的新鲜度,从而导致HDFS群集上不必要的I/O,并大大加快磁盘降级速度。此外,更多的数据表更新意味着更多的文件版本和HDFS文件数量的爆炸性增长。反过来,这些需求导致HDFS NameNode不稳定和更高的计算成本。
为了解决这些日益增长的问题,我们实现了第二个表类型,即读取时合并。由于读取时合并通过动态合并数据来利用接近实时的数据,因此我们谨慎使用此功能以避免查询端计算成本。我们的读取时合并部署模型由三个独立的作业组成,包括一个引入新数据(包括插入、更新和删除)的接收作业,一个异步地、积极地压缩少量最近分区中的更新/删除的次要压缩作业,以及一个缓慢而稳定地压缩大量较旧分区中的更新/删除的主要压缩作业。这些作业中的每一个都以不同的频率运行,次要作业和摄取作业的运行频率比主要作业更高,以确保其最新分区中的数据以列格式快速可用。使用这样的部署模型,我们能够以列式格式向数千个查询提供新鲜数据,并将查询端合并成本绑定到最近的分区。使用Merge-on-Read,我们能够解决上面提到的所有三个问题,并且Hudi表几乎不会受到对我们的数据湖的任何数量的传入更新或删除的影响。现在,在Uber,我们根据使用案例同时利用Apache Hudi的写入时复制和读取时合并功能。
多亏了Hudi,优步每天向我们的150PB数据湖摄取超过5000亿条记录,跨越10,000多个表和数千条数据管道,每天使用超过30,000个虚拟核心。Hudi表每周通过我们的各种服务提供100多万次查询。
优步在2017年开源了Hudi,让其他人享受到了大规模吸收和管理数据存储的解决方案的好处,将流处理带入了大数据。随着Hudi毕业于Apache软件基金会的顶级项目,t
如果没有良好的标准化和原语,数据湖可能很快就会变成不可用的“数据沼泽”。这样的沼泽不仅需要大量的时间和资源来协调、清理和修复表,而且还迫使各个服务所有者构建复杂的算法来进行调优、洗牌和事务,从而给您的技术堆栈带来了不必要的复杂性。
如上所述,Hudi通过无缝接收和管理分布式文件系统上的大型分析数据集,帮助用户控制他们的数据湖,从而弥补了这些空白。构建数据湖是一个多方面的问题,需要在数据标准化、存储技术、文件管理实践方面进行投资,在接收数据与查询数据等之间选择正确的性能权衡。当我们在建设Hudi的过程中与大数据社区的其他成员交谈时,我们了解到这样的问题在许多工程组织中非常猖獗。我们希望开源以及在过去几年中与Apache社区合作以Hudi为基础,能让其他人更深入地了解他们自己的大数据操作,以改进跨行业的应用程序。除了优步,阿帕奇胡迪还在几家公司的生产中使用,包括阿里巴巴云、Udemy和腾讯。
Hudi通过对数据集实施图案化,帮助用户构建更强大、更新鲜的数据湖,提供高质量的洞察力。
在优步,拥有世界上最大的交易数据湖之一,让我们有机会识别独特的Apache Hudi使用案例。由于解决问题和创造这种规模的效率可能会产生重大影响,因此我们有直接的动机去更深入地研究。在优步,我们已经使用高级Hudi原语(如增量拉)来帮助构建链式增量管道,以减少作业的计算占用空间,否则这些作业将执行大量扫描和写入。我们根据特定的用例和需求调整读取时合并表的压缩策略。自从我们将Hudi捐赠给Apache基金会后的最近几个月里,Uber贡献了一些功能,比如用于高效文件系统访问的嵌入式时间线服务,删除重命名以支持云友好部署,以及提高增量拉取性能,仅举几例。
在接下来的几个月里,优步打算为Apache Hudi社区贡献许多新功能。其中一些功能通过优化计算使用以及提高数据应用程序的性能来帮助降低成本。我们还在更深入地研究如何根据访问模式和数据应用程序要求改进存储管理和查询性能。
有关我们计划如何实现这些目标的更多信息,您可以阅读Uber的Hudi团队向更广泛的Apache社区提出的一些RFC(包括支持列索引的智能元数据和O(1)查询规划、高效地将表引导到Hudi、用于快速插入的记录索引)。
随着Apache Hudi毕业于一个顶级Apache项目,我们很高兴能为该项目雄心勃勃的路线图做出贡献。Hudi使Uber和其他公司能够使用开源文件格式在未来证明其数据湖的速度、可靠性和事务处理能力,从而抽象出许多大数据挑战,并构建丰富和便携的数据应用程序。
Apache Hudi是一个不断发展壮大的社区,有着令人兴奋的、不断发展的开发路线图。如果你有兴趣为这个项目做贡献,请点击这里。