关于meta:Meta公司内部项目RaptorX将Presto性能提升10倍

22次阅读

共计 5985 个字符,预计需要花费 15 分钟才能阅读完成。

概要速览

RaptorX 是 Meta(前“Facebook 公司”,下文统称“Meta”)公司的一个外部项目名称,目标是为了升高查问提早,让 Presto 的查问性能大大超越原生(vanilla)Presto,这篇文章介绍了 RaptorX 的要害模块——分层缓存。

有了分层缓存,咱们可能将查问性能晋升 10 倍。这一新的架构不仅能够完胜像 Raptor 之类以性能为导向的连接器,还具备向存储拆散化(即存算拆散架构)进行继续拓展和反对的额定劣势。

存储拆散化存在的问题

存储拆散化是行业朝着独立存算扩容倒退的必然趋势,可能帮忙云服务供应商降低成本。Presto 自身反对这样的存算拆散架构,而数据能够从部署了 Presto 的服务器之外的近程存储节点获取。

尽管如此,存算拆散对查问提早提出了新的挑战,因为在网络饱和的状况下,通过网络扫描海量数据会受到 IO 的限度。此外,元数据拜访和操作门路也须要通过网络来获取数据的地位;几个元数据 RPC 来回就能轻易地把提早贬低到一秒以上,下图用橙线示意 Hive 连接器的 IO 相干操作门路,每条门路都可能成为查问性能的瓶颈。

RaptorX:搭建分层缓存解决方案

过来,为了解决网络饱和的问题,Presto 通过内嵌的 Raptor 连接器,将数据从远端存储加载到本地的 SSD(固态硬盘),从而实现快速访问,然而,这种解决方案与计算 / 存储共享节点差异不大,有悖于存算拆散的理念。该解决方案的毛病很显著:要么因为 worker 节点的 SSD 空间已满而节约 CPU,要么因为 CPU 受限而节约 SSD 容量。于是,Meta 启动了 RaptorX 我的项目的开发。

RaptorX 是为了将 Presto 查问性能晋升至多 10 倍而发展的一个外部我的项目,其中分层缓存是 RaptorX 我的项目胜利的要害。当存储节点与计算节点拆散时,缓存的作用尤为显著。开发 RaptorX 的目标不是为了推出一个新的连接器或产品,而是结构一套内嵌的解决方案,让现有的工作负载无需迁徙即可间接从中获益,该解决方案目前次要针对许多工作负载罕用的 Hive 连接器。

下图展现了缓存解决方案的整体架构,该缓存具备分层构造,本文会具体介绍:

* Metastore 版本化的缓存计划:咱们把表 / 分区信息缓存到 coordinator 中,鉴于元数据是可变的,就像 Iceberg 或 Delta Lake 那样,因而信息是被版本化的,咱们只与 metastore 同步版本信息,并仅在以后版本生效时去获取最新版本。* 文件列表缓存:将来自远端存储分区目录的文件列表缓存起来。* 片段后果缓存:在 leaf worker 的本地 SSD 上缓存局部计算结果。因为查问会一直变动,所以咱们须要使用裁剪技术来简化查问打算。* 文件句柄(file handle)和 footer 的缓存:在 leaf worker 内存中缓存关上的文件描述符(file descriptor)和 stripe/ 文件 footer 信息,因为在读取文件时这些数据往往会被频繁拜访。* Alluxio 数据缓存:在 leaf worker 的本地 SSD 上用对齐的 1MB 大小数据块来缓存文件段。该库(library)是通过 Alluxio 的缓存服务搭建的。* 亲和调度器:是指依据文件门路固定地向对应 worker 发送申请,从而使缓存命中率最大化的调度器(scheduler)。

Metastore 版本化的缓存

Presto coordinator 会缓存表的元数据(模式、分区列表和分区信息),以防止向 Hive Metastore 发动耗时很长的 getPartitions 调用,然而,Hive 表的元数据是可变的,所以咱们须要进行版本治理并确定已缓存的元数据是否无效,因而,coordinator 为每个缓存的键值对赋予了一个版本号。当收到读取申请时,coordinator 会查问 Hive Metastore,获取(未被缓存的)分区信息,或者与 Hive Metastore 核查确认曾经缓存的信息是否是最新的。尽管和 Hive Metastore 进行近程交互的操作不可避免,但与获取全副分区信息相比,版本匹配的老本绝对较低。

文件列表缓存

Presto coordinator 将文件列表缓存在内存中,从而防止对远端存储发动耗时很长的 listFile 调用。这只实用于关闭的目录, 而对于凋谢分区,为了确保数据的实时性,Presto 不会缓存这些目录。凋谢分区的一个次要用例是反对近实时的数据导入和解决。在这种状况下,数据导入引擎(如微批数据 micro batch)将一直向凋谢分区写入新的文件,以便 Presto 能够读取近实时的数据。其余诸如压缩、metastore 更新或为近实时导入数据创立正本等详细信息不在本文的探讨范畴内。

片段后果缓存

运行在 leaf 阶段的 Presto worker 能够决定将局部计算结果缓存在本地 SSD 上,这么做是为了避免屡次查问时进行反复计算。最典型的用例是将执行打算的包含扫描、过滤、投影和 / 或聚合的片段后果缓存在 leaf 阶段。

例如,假如一个用户发送了以下查问,其中 ds 是一个分区列:

SELECT SUM(col) FROM T WHERE ds BETWEEN’2021-01-01′ AND ‘2021-01-03’

对 2021-01-01、2021-01-02 和 2021-01-03 每个分区(更精确地说是相应的文件)计算的局部求和后果将被缓存在 leaf worker 上,造成一个“片段后果”,当初假如用户发送了另外一项查问:

SELECT sum(col) FROM T WHERE ds BETWEEN ‘2021-01-01’AND ‘2021-01-05’

当初,Leaf worker 便能够间接从缓存中获取 2021-01-01、2021-01-02 和 2021-01-03 的片段后果(局部求和后果),并且只须要对 2021-01-04 和 2021-01-05 两个分区计算局部求和即可。

因为片段后果是基于 leaf 查问片段的,用户能够增加或删除过滤器或投影,因而非常灵活。上述例子表明,只蕴含分区列的过滤器很容易解决。然而为防止因为频繁变动的非分区列过滤器造成的缓存生效,咱们引入了基于分区统计信息的裁剪策略,请看下述查问,其中 time 是一个非分区列:

SELECT SUM(col) FROM T
WHERE ds BETWEEN '2021-01-01'AND'2021-01-05'
ANDtime > now() - INTERVAL'3' DAY

请留神:now() 函数的值始终在变,如果 leaf worker 依据 now() 的绝对值来缓存打算片段,简直不可能会命中缓存,然而,如果 predicate(谓词条件)time > now() – INTERVAL ‘3’ DAY 是对于大多数分区来说为真(true)的“宽松”条件,咱们能够在调度时把该谓词从打算中删除。

例如,如果明天是 2021-01-04,那么咱们晓得对于分区 ds = 2021-01-04,predicate time > now() – INTERVAL ‘3’ DAY 总是成立的。

如下图所示,一般而言,它蕴含一个谓词条件和 3 个分区 (A, B, C),以及各分区同谓词条件相干的最小值(min)、最大值(max)的统计信息 (stats)。当分区统计域与谓词域没有任何重叠时(如分区 A),咱们能够间接裁剪掉该分区,不须要向 worker 发送分片(split)。如果分区统计域齐全蕴含在谓词域中(如分区 C),那么咱们不须要该谓词,因为它对这个特定的分区总是成立的,咱们能够在进行打算比照时省略该谓词条件。对于其余与谓词有一些重叠的分区,咱们仍须要用给定的过滤器扫描整个分区。

文件描述符和 footer 缓存

Presto worker 将文件描述符缓存在内存中,防止对远端存储进行耗时较长的 openFile 调用。此外,worker 还会把常常拜访到的列文件和 stripe footer 缓存在内存中。目前反对的文件格式是 ORC,DWRF 和 Parquet。在内存中缓存此类信息的起因是 footer 作为针对数据建设的索引信息通常具备高缓存命中率。

Alluxio 数据缓存

Alluxio 数据缓存是一个次要个性区别于被淘汰的 Raptor 连接器。Presto worker 每次进行读取操作时将远端存储数据以它原始格局(通过压缩或者可能也通过加密)缓存在本地 SSD 上。对于未来的读取申请,如果读取范畴内的数据曾经缓存在本地 SSD 上,则该读取申请将间接从本地 SSD 返回后果。缓存库是咱们与 Alluxio 和 Presto 开源社区独特搭建的。

缓存机制将每次读取对齐成 1MB 固定大小的数据块,这里的 1MB 是能够依据不同的存储能力进行配置的。比方,假如 Presto 发动一次从偏移量 0 开始的长度为 3MB 的读取申请,那么 Alluxio 缓存会查看 0 -1MB、1-2MB 和 2 -3MB 的数据块是否曾经缓存在磁盘上,而后只近程获取尚未被缓存的数据块。缓存革除策略基于 LRU,会从磁盘上删除最久没被拜访过的数据块。Alluxio 数据缓存为 Hive 连接器提供了规范的 Hadoop 文件系统接口,并且基于专门用来撑持规模达到 Meta 级别工作负载的高性能、高并发且可容错的存储引擎,以通明的形式对申请的数据块进行缓存。

软亲和调度

为了最大水平地进步 worker 的缓存命中率,coordinator 须要将同一文件的申请调度给同一个 worker。因为文件的一部分很有可能曾经被缓存在那个特定的 worker 上了。调度策略是“软”的,也就是说,如果指标 worker 太忙或不可用,调度器会退而求其次,安顿给它的备选 worker 进行缓存,或者在必要时间接跳过不予缓存。该调度策略确保了缓存不在要害门路上,但依然可能晋升性能。

Performance 性能

Meta 曾经在公司外部全面部署了 RaptorX 缓存并进行了实战测试。为了与原生(vanilla)Presto 进行性能比拟,咱们在一个蕴含 114 个节点的集群上进行了 TPC- H 基准测试。每个 worker 都有 1TB 的本地 SSD,每个工作配置 4 个线程。咱们在远端存储中筹备了放大系数(scale factor)为 100 的 TPC- H 表。下图展现了 Presto 和配备了分层缓存的 Presto 之间的性能比照后果。

从基准测试后果来看,像 Q1、Q6、Q12-Q16、Q19 和 Q22 这样的重扫描或重聚合的查问都能实现超过 10 倍的提早改善。甚至像 Q2、Q5、Q10 或 Q17 这样的重关联查问也有 3 - 5 倍的提早改善。

User Guide 用户指南

要齐全启用该性能,咱们须要为 worker 装备本地的 SSD,为了可能启用本文所述的各个缓存层,请进行以下配置:

调度 (/catalog/hive.properties):

hive.node-selection-strategy=SOFT_AFFINITY

Metastore 版本化的缓存 (/catalog/hive.properties):

hive.partition-versioning-enabled=true
hive.metastore-cache-scope=PARTITION
hive.metastore-cache-ttl=2d
hive.metastore-refresh-interval=3d
hive.metastore-cache-maximum-size=10000000

文件列表缓存 (/catalog/hive.properties):

hive.file-status-cache-expire-time=24h
hive.file-status-cache-size=100000000
hive.file-status-cache-tables=*

数据缓存 (/catalog/hive.properties):

cache.enabled=true
cache.base-directory=file:///mnt/flash/data
cache.type=ALLUXIO
cache.alluxio.max-cache-size=1600GB

片段后果缓存 (/config.properties and /catalog/hive.properties):

fragment-result-cache.enabled=true
fragment-result-cache.max-cached-entries=1000000
fragment-result-cache.base-directory=file:///mnt/flash/fragment
fragment-result-cache.cache-ttl=24h
hive.partition-statistics-based-optimization-enabled=true

文件和 stripe footer 缓存 (/catalog/hive.properties):

● 针对 ORC 或 DWRF 格局:hive.orc.file-tail-cache-enabled=true

hive.orc.file-tail-cache-size=100MB
hive.orc.file-tail-cache-ttl-since-last-access=6h
hive.orc.stripe-metadata-cache-enabled=true
hive.orc.stripe-footer-cache-size=100MB
hive.orc.stripe-footer-cache-ttl-since-last-access=6h
hive.orc.stripe-stream-cache-size=300MB
hive.orc.stripe-stream-cache-ttl-since-last-access=6h

针对 Parquet 格局:

hive.parquet.metadata-cache-enabled=true
hive.parquet.metadata-cache-size=100MB
hive.parquet.metadata-cache-ttl-since-last-access=6h

文章贡献者:

Meta:Abhinav Sharma, Amit Dutta, Baldeep Hira, Biswapesh Chattopadhyay, James Sun, Jialiang Tan, Ke Wang, Lin Liu, Naveen Cherukuri, Nikhil Collooru, Peter Na, Prashant Nema, Rohit Jain, Saksham Sachdev, Sergey Pershin, Shixuan Fan, Varun Gajjala
Alluxio: Bin Fan, Calvin Jia, HaoYuan Li
Twitter: Zhenxiao Luo
Pinterest: Lu Niu
援用

正文完
 0