686 讀數
686 讀數

Uber Presto 本地缓存的设计与实现

经过 Bin Fan2022/06/03
Read on Terminal Reader
Read this story w/o Javascript

太長; 讀書

在上一篇博客中,我们介绍了 Uber 的 Presto 用例以及我们如何协作实现 Alluxio 本地缓存以克服加速 Presto 查询的不同挑战。第二部分讨论对本地缓存元数据的改进。

Companies Mentioned

Mention Thumbnail
Mention Thumbnail

Coin Mentioned

Mention Thumbnail
featured image - Uber Presto 本地缓存的设计与实现
Bin Fan HackerNoon profile picture


上一篇博客中,我们介绍了 Uber 的 Presto 用例以及我们如何合作实现 Alluxio 本地缓存以克服加速 Presto 查询的不同挑战。第二部分讨论对本地缓存元数据的改进。

本地缓存的文件级元数据

动机

首先,我们要防止过时的缓存。底层数据文件可能会被第三方框架更改。请注意,这种情况在 Hive 表中可能很少见,但在 Hudi 表中很常见。


其次,每天从 HDFS 读取的不重复数据可能很大,但我们没有足够的缓存空间来缓存所有数据。因此,我们可以通过为每个表设置一个配额来引入范围配额管理。


第三,元数据应该在服务器重启后可以恢复。我们将元数据存储在内存而不是磁盘中的本地缓存中,这使得当服务器关闭并重新启动时无法恢复元数据。

高级方法

因此,我们提出了文件级元数据,它保存并保存了我们缓存的每个数据文件的最后修改时间和范围。文件级元数据存储应持久保存在磁盘上,以便重启后数据不会消失。


随着文件级元数据的引入,数据将有多个版本。数据更新时会产生一个新的时间戳,对应一个新的版本。对应于这个新时间戳创建一个存储新页面的新文件夹。同时,我们会尝试移除旧的时间戳。

缓存数据和元数据结构

如上图,我们有两个文件夹对应两个时间戳:timestamp1和timestamp2。通常,系统运行时,不会同时有两个时间戳,因为我们会删除旧的时间戳1,只保留时间戳2。但是,在服务器繁忙或高并发的情况下,我们可能无法按时移除时间戳,这种情况下我们可能同时有两个时间戳。此外,我们维护一个元数据文件,该文件保存 protobuf 格式的文件信息和最新的时间戳。这确保了 Alluxio 的本地缓存只从最新的时间戳中读取数据。当服务器重启时,会从元数据文件中读取时间戳信息,以便正确管理配额和上次修改时间。


元数据意识

缓存上下文

由于 Alluxio 是一个通用的缓存解决方案,它仍然需要像 Presto 这样的计算引擎将元数据传递给 Alluxio。因此,在 Presto 站点上,我们使用 HiveFileContext。对于 Hive 表或 Hudi 表中的每个数据文件,Presto 都会创建一个 HiveFileContext。 Alluxio 在打开 Presto 文件时会使用这些信息。


在调用 openFile 时,Alluxio 会创建一个新的 PrestoCacheContext 实例,该实例保存 HiveFileContext 并具有范围(四个级别:数据库、模式、表、分区)、配额、缓存标识符(即文件路径的 md5 值)和其他信息。我们将把这个缓存上下文传递给本地文件系统。因此,Alluxio 可以管理元数据并收集指标。


Presto 端的每个查询指标聚合

除了将数据从 Presto 传递到 Alluxio 之外,我们还可以回调 Presto。在执行查询操作时,我们会知道一些内部指标,例如读取的数据有多少字节命中缓存以及从外部 HDFS 存储读取了多少字节的数据。

如下图,我们将包含PrestoCacheContext的HiveFileContext传递给本地缓存文件系统(LocalCacheFileSystem),之后本地缓存文件系统回调(IncremetCounter)给CacheContext。然后,这个回调链将继续到 HiveFileContext,然后到 RuntimeStats。


在 Presto 中,RuntimeStats 用于在执行查询时收集指标信息,以便我们进行聚合操作。之后,我们可以在 Presto 的 UI 或者 JSON 文件中看到本地缓存文件系统的信息。我们可以让 Alluxio 和 Presto 与上述流程紧密协作。在 Presto 方面,我们有更好的统计数据;在 Alluxio 方面,我们对元数据有更清晰的了解。

未来的工作

性能调优

由于上述回调过程使 CacheContext 的生命周期显着增长,我们遇到了一些 GC 延迟上升的问题,我们正在努力解决。

采用语义缓存 (SC)

我们将根据我们建议的文件级元数据来实现语义缓存(SC)。例如,我们可以将数据结构保存在 Parquet 或 ORC 文件中,例如页脚、索引等。

更高效的反序列化

为了实现更高效的反序列化,我们将使用 flatbuf 代替 protobuf。虽然在 ORC 工厂中使用了 protobuf 来存储元数据,但我们发现在 Alluxio 与 Facebook 的合作中,ORC 的元数据带来了超过 20-30% 的总 CPU 使用率。因此,我们计划用 flatbuf 替换现有的 protobuf 来存储缓存和元数据,这有望显着提高反序列化的性能。


总而言之,与上一篇博客一起,这个由两部分组成的博客系列分享了我们如何根据 Uber 的 Presto 和 Alluxio 社区之间最近的开源合作,为我们的 Presto 车队所需的热数据创建一个新的缓存层。这种架构上简单而干净的方法可以通过托管 SSD 和一致的基于散列的软关联调度显着减少 HDFS 延迟。加入我们社区Slack 频道的 9000 多名成员,了解更多信息。

关于作者

Chen Liang是 Uber 交互式分析团队的高级软件工程师,专注于 Presto。在加入优步之前,Chen 是 LinkedIn 大数据平台的一名软件工程师。 Chen 还是 Apache Hadoop 的提交者和 PMC 成员。陈先生拥有杜克大学和布朗大学两个硕士学位


王贝南博士是来自 Alluxio 的软件工程师,是 PrestoDB 的提交者。在加入 Alluxio 之前,他是 Twitter Presto 团队的 Tech Lead,他为 Twitter 的数据平台构建了大规模的分布式 SQL 系统。他在性能优化、分布式缓存和大容量数据处理方面拥有 12 年的经验。他获得了博士学位。雪城大学计算机工程专业,研究分布式系统的符号模型检查和运行时验证。


也在这里发布。

Trending Topics

blockchaincryptocurrencyhackernoon-top-storyprogrammingsoftware-developmenttechnologystartuphackernoon-booksBitcoinbooks