本文转载自 InfoQ 官网
作者:Alluxio-钟荣荣;Meta-James Sun & Ke Wang
Raptor 是用来支持 Meta(以前的 Facebook)中的一些关键交互式查询工作负载的 Presto 连接器(presto-raptor)。尽管 ICDE 2019 的论文 Presto:SQL on Everything(https://research.facebook.com...)中提到过这一特性,但它对于许多 Presto 用户来说仍然有些神秘,因为目前还没有关于此特性的可用文档。本文将介绍 Raptor 的历史,以及为什么 Meta 最终替换了它,转而采用基于本地缓存的新架构 RaptorX。
Raptor 简介
一般来说,Presto 作为一个查询引擎并不具备存储空间,因此开发了连接器来查询不同的外部数据源。这个框架非常灵活,但在存算分离的架构中,很难提供低延迟保证。网络和存储延迟导致很难确保数据访问的稳定性。为了解决这个问题,Raptor 被设计成 Presto 的独享存储引擎(shared-nothing storage engine)。
>> 动机—AB 测试框架中的一个初始用例 <<
在 Meta 公司,新的产品特性通常要经过 AB 测试,然后才能大范围发布。AB 测试框架允许工程师配置实验,在实验组启用新特性,然后通过监控一些关键指标与对照组进行比较。该框架为工程师提供了一个 UI(用户界面)来分析他们的实验统计数据,从而将配置转换为 Presto 查询,查询语句是已知且有限的。查询通常连接多个大型数据集,其中包括用户、设备、测试、事件属性等。这个用例的基本需求是:
1.准确性:数据必须完整、准确,不能有偏差
2.灵活性:用户应该能够根据分析需求随意划分其运行结果;
3.实时性:测试结果应在数小时内获得;
4.交互延迟短:查询需要在几秒钟内返回结果;
5.高可用:作为产品开发的关键服务,服务的宕机时间必须很短。
Presto 在典型的仓库设置中(比如使用 Hive 连接器直接查询仓库数据)可以轻松满足前两个要求,但无法满足其他的要求。仓库数据大多是 T+1 导入,没有近实时的数据导入,因此不能满足实时性的要求。此外,Meta 的数据中心已经转用存算分离的架构,当以高 QPS (查询吞吐率)扫描大型表时,无法保证低延迟。同时,典型的 Presto 部署会停止整个集群,因此也不能满足高可用需求。
为了支持这一关键用例,我们开始了 Raptor 的产品化进程。
>>> RaptorX 架构 <<<
Raptor 连接器使用 MySQL 作为 metastore 来存储表和文件元数据。表数据存储在每个 worker 节点的本地磁盘上,并定期备份到外部存储系统,以便在 worker 节点崩溃时能够进行数据恢复。数据以足够小的批量方式导入 Raptor 集群中,从而确保分钟级别的延迟,满足实时性要求。此外,还创建了备用集群,提供高可用性。
想要了解更多 Raptor 存储引擎的相关信息,请查看附录—Raptor 架构信息(https://prestodb.io/blog/2022...)或观看附录—Raptor 讲座(https://prestodb.io/blog/2022...)。
局限
通过存算耦合,Raptor 集群可以支持低延迟、高吞吐量的查询工作负载。但是,这种架构带来了以下几个问题:
集群利用率低
Raptor 集群的大小通常取决于需要存储多少数据。由于存算耦合,随着表的增多,将需要更多的 worker 提供足够的存储空间,即使在集群空闲时段,重新将机器分配给其他业务使用的难度也变得非常大。
尾部性能较差
由于数据是对应分配给 worker 节点的,如果一个 worker 节点宕机或变慢,必然会影响查询性能,难以提供稳定的尾部性能。
工程开销较大
Raptor 需要很多存储引擎特有的特性和处理功能的支持,比如数据导入/释放、数据压缩、数据备份/恢复、数据安全等。对于直接查询 Meta 数据仓库的 Presto 集群而言,所有这些服务都由专门的团队管理,所有用例都能从中受益。而对于 Raptor 来说,情况就不同了,这导致了工程开销。
运维开销较高
由于 Raptor 集群需要部署额外的存储系统,因此也就带来额外的运维开销。不同的集群配置和行为意味着需要单独建立 oncall 的处理流程。
潜在的安全和隐私漏洞
随着安全和隐私需求的增加,安全与隐私策略的统一实现变得更加重要。使用单独的存储引擎使得这些策略执行起来非常困难且脆弱。
RaptorX 的启用
Raptor 有着很多的痛点,因此从 2019 年开始,Meta 的工程师们就在重新思考 Raptor 的未来,是否有可能既从本地闪存中受益,又无需承担存算紧耦合架构带来的代价?最终确定的方向是在原生数据仓库之上添加一个新的本地缓存层。这个项目作为 Presto Raptor 连接器用例的替代品被命名为 RaptorX。
从技术层面来讲,RaptorX 项目与 Raptor 无关。直观来说,同样的闪存设备在 RaptorX 里被当作数据缓存使用来存储 Ratpor 表,因此将热数据存放在计算节点上。将本地闪存作为缓存使用而不作为存储引擎使用的优点如下:
● Presto 无需管理数据生命周期;
● 单个 worker 故障导致的数据丢失对查询性能的影响较小;
● 缓存作为文件系统层的一个特性,是 presto-hive 连接器的一部分,因此 RaptorX 集群的架构类似于其他 presto 集群,减少了运维开销。
>>> RaptorX 架构 <<<
Raptor 和 RaptorX 的根本区别是如何使用 worker 上的本地固态硬盘(SSD)。在 RaptorX 中,Presto Worker 使用 Alluxio 在本地缓存文件数据。不同表列的访问模式可能差异很大,像 ORC 和 Parquet 这样的列式文件格式通常用于数据存储,增加文件中的数据本地性。通过在列式文件上以较小的页面大小缓存文件片段,只有频繁访问的数据才会被保存在接近计算的地方。Presto coordinator 会尝试将处理相同数据的计算任务调度到相同的 worker 节点上,以提高缓存效率。RaptorX 还实现了文件 footer 和元数据缓存,以及其他能进一步提高性能的智能缓存策略。
要了解更多有关 RaptorX 的信息,参见 《RaptorX: 将 Presto 性能提升十倍》(https://prestodb.io/blog/2021...)。
>>> RaptorX 和 Raptor 性能基准测试 <<<
我们对 RaptorX 和 Raptor 进行了基准性能对比测试。基准测试运行在一个有大约 1000 个 Worker 节点和一个 coordinator 的集群上。Raptor 和 RaptorX 使用相同的硬件,整个数据集都能够缓存到 RaptorX 的本地固态硬盘中,因此缓存
从基准测试结果中可以看到,RaptorX 的 P90 延迟与 Raptor 相比降低了一半。RaptorX 中的平均查询延迟和 P90 查询延迟之间的差异要比 Raptor 小得多。这是因为在 Raptor 中,数据被物理绑定到计算它的 worker 点上,因此运行慢的节点将不可避免地影响查询延迟。而在 RaptorX 中,我们采用软亲和(soft affinity) 调度。软亲和调度将选择两个 worker 节点作为处理分片(split)的候选节点。如果首选的 worker 节点运行正常,则选择该节点,否则将选择辅助(secondary) worker 节点。数据很有可能在多个节点上缓存,因此对整体工作负载的调度策略可以进一步优化,从而达到更好的 CPU 负载均衡。
>>> 从 Raptor 迁移到 RaptorX <<<
Meta 公司所有以前的 Raptor 用例都迁移到了 RaptorX 上, RaptorX 提供了更好的用户体验,并且易于扩展。
A/B 测试框架
在前一节中,我们提到了 A/B 测试框架的要求是:准确性、灵活性、实时性、低交互延迟和高可用性。因为 RaptorX 是 Hive 原始数据的缓存层,所以 Hive 保证了数据的准确性。它享受所有来自核心 Presto 引擎的查询优化,以及 Hive 连接器中的许多特定优化。基准测试结果表明,RaptorX 的平均查询和 P90 查询延迟都优于 Raptor。对于实时性要求,我们能够从 Meta 的近实时仓库数据导入框架优化中受益,它提高了所有 Hive 数据的实时性。与 Raptor 一样,备用集群保证了高可用性。
在迁移过程中,由于用户体验良好,测试框架的使用量增长了 2 倍。RaptorX 集群能够按照与迁移前的 Raptor 集群相同的容量支持额外的用量。集群的 CPU 资源得到充分利用,无需担心存储限制。
仪表板
在 Meta 中 Raptor 的另一个典型用例是优化仪表板体验。Presto 用于支持 Meta 中的许多仪表板用例,一些数据工程团队通过预聚合一些数据表,并且手动导入指定的 Raptor 集群来获得更好的查询性能。在迁移到 RaptorX 之后,数据工程师便可以省去数据导入操作,也不再需要担心基础表(base tables)和预聚合表之间的数据一致性问题,同时,P50 以上的大多数分位的查询延迟的降幅都达到了 30%左右。
>>> Raptor 范围之外 <<<
由于 RaptorX 在正常的 Hive 连接器工作负载下作为 booster 使用起来很容易,我们也在 Meta 的数仓交互式工作负载中启用了 RaptorX。这些是多租户集群,通过 Presto 处理几乎所有 Hive 数据的非 ETL 查询,包括 Tableau、内部仪表板、各种自动生成的 UI 分析查询、各种内部工具生成的工作负载、工作流原型(pipeline prototyping)、调试、数据探索等。RaptorX 为这些集群提供了支持,提高了相同数据集的查询性能。
附录
Raptor 架构信息
Raptor 表是根据哈希函数进行桶(bucket)划分的。来自同一个 bucket 的数据被存储在同一个 worker 节点上。在同一列上的多个表被称为一个 distribution。一个表桶可以包含多个分片(shard), 而分片是 Raptor 数据的基本不可变单位, 以 ORC 格式的文件存储。表也可以有排序属性,可以更好地优化查询。
执行优化
Raptor 作为 Presto 的本地存储引擎,允许 Presto 将计算安排在数据节点上,从而提供低延迟、高吞吐量的数据处理能力。除了通用的 SQL 优化外,Raptor 的数据组织方式还能实现更多的执行优化。
● 本地关联:当在桶列上关联同一 distribution 的表时,Raptor 将进行本地关联(Collocated Join),因为具有相同连接键的数据在同一个 worker 上,避免了重新分配。
● 数据裁剪: Raptor 可以进行分片粒度和 ORC 读取器粒度的裁剪
o 分片粒度的裁剪:分片的列范围存储在元数据中,可以根据查询谓词跳过分片。如果表有排序属性,分片将在该 worker 内被排序,这也可用于分片裁剪。
o ORC 读取器粒度的裁剪:ORC 读取器基于谓词,通过利用 Stripe(一组行数据)元数据针对 Stripe 和行组进行裁剪。如果数据是有序的,排序属性也有助于数据裁剪。
其他特性
● 时间列:一个时间或日期类型的列可以被指定为时间列。如果指定了一个时间列,Raptor 会在分片上严格按天进行限制(即一个 shard 里的记录都是属于某一天的)。鉴于数据保留策略,这将能够提高大表的数据留存性能。
● 后台压缩:为了保证实时性,数据通常是以小的时间粒度导入 Raptor 的,这可能导致产生很多小文件,对查询性能不利。Raptor worker 定期运行后台作业,将多个小分片压缩成大分片,并进行外部排序,保证排序属性。
● 数据恢复:如果某个 worker 发生故障,coordinator 将在集群的其他节点上重新分配故障 worker 的数据。所有 worker 将从备份存储中下载必要的数据。在恢复过程中,如果某个查询需要访问缺失数据,该操作将被阻止,直到数据下载/恢复完毕。
● 数据清理:每个 worker 都有一个后台进程,将其分配的数据与本地数据进行比较,从而恢复缺失的数据,更新陈旧的数据。
● 数据再平衡:如果 coordinator 检测到数据不平衡(例如,增加了新的 worker 节点),它会修复不平衡的数据分布。
Raptor 讲座
引用
如需了解更多有关 Raptor 的信息, 可点击此链接:Presto Raptor: MPP Shared-Nothing Database on Flash(https://engineering.fb.com/20...),查看 2016 年 [email protected] 会议上关于 Raptor 的公开讲座。
想要获取更多有趣有料的【活动信息】【技术文章】【大咖观点】,请关注[[Alluxio智库]](https://page.ma.scrmtech.com/...):