B站基于缓存优化 PRESTO 集群查询性能

导读:本次分享主题为 B 站 Presto 集群查询性能的优化,首先会简单介绍 Presto以及 B 站内部 Presto 集群的架构。接下来讲解针对 Presto 做的改造,主要是 Presto 搭配 Alluxio 和 Presto 搭配 Alluxio local cache 的使用。最后会对后续计划开展的工作做简要说明。

本次介绍的六个部分为:

1. 集群架构

2. Presto 简介

3. Presto 改造

4. Presto on Alluxio

5. Presto Local Cache

6. 后续工作


分享嘉宾|杨洋 bilibili 大数据开发工程师

编辑整理|陈昱彤 纽约大学

出品社区|DataFun


01/集群架构

1. B 站 SQL On Hadoop

下图为 B 站 Presto 集群的架构图,最上层是内部的一些数据服务,所有服务统一接入 Dispatcher。Dispatcher 是一套内部自研的服务,根据查询 HDFS 的数据量、目前引擎的负载情况等将用户提交的 query 路由到相应的引擎进行执行。对于 presto 的查询语法和 hive/spark 语法可能出现的不兼容问题,我们引进了 Linkedin 的开源软件 Coral,将 hive 和 spark 的语法转换为 presto 的语法进行执行。

计算引擎的路由逻辑:对于查询量比较小的 sql,会优先路由到 presto 进行执行,如果失败则降级到 spark 进行执行,再失败则降级到 hive 进行执行。

调度平台(ETL):用户可以通过调度平台编写调度作业来执行调度任务,具体是由 yarn 来调度。

Ranger:目前 HDFS 和 hive/presto/spark 都已经接入到 Ranger 进行统一的权限控制。权限控制包括表字段级别的控制以及 column masking 和 row filter 的控制。

B站基于缓存优化 PRESTO 集群查询性能_第1张图片

 

2. Presto 集群现状

目前 Presto 包括了四套集群,分为两个机房(IDC1 和 IDC2)。除了Cluster3 之外的集群都实现了跨机房功能,目前集群数最多的为 IDC2 的 Cluster1(441 为集群数量,2 为 coordinator 数量)。Presto 集群平均每月作业数量 500w,每日作业数约 16w~17w。平均每月读 HDFS 数据量约 300PB,每日 10PB。

 

3. Presto 集群架构

Presto 集群的架构大致如下,用户作业提交后,会先通过一个开源组件Presto-Gateway,将 sql 作业路由到对应的 IDC 机房中相对应的 presto 集群中的 coordinator 节点进行执行。

B站基于缓存优化 PRESTO 集群查询性能_第2张图片

 

--

02/Presto 简介

1. Presto 历史

Presto 是 2013 年 11 月份由 Facebook 开源的一个分布式 sql 查询引擎,设计之初是为了进行 OLAP 数据查询,支持标准的 ANSI SQL,也支持多数据源。在 2019 年 1 月时 Presto 内部分裂出了两个分支:PrestoSQL(trino)和 PrestoDB。PrestoSQL 相对于 PrestoDB 来说社区活跃度较高且更加注重 OLAP 的方向,而后者相对更注重 ETL 的方向。

B站基于缓存优化 PRESTO 集群查询性能_第3张图片

2. Presto 基本原理

Presto 是一个典型的主从架构,它由一台 coordinator 和多个 worker 构成,Presto worker 启动时会在 coordinator 进行注册。Presto 集群作业的执行流程是:

1.coordinator 收到作业后通过 sql 解析器对作业进行解析生成语法树, LogicPlanner 再对语法树进行语义分析,将 AST 转为逻辑执行计划,同时使用优化器进行优化。接着通过 DistributedPlanner 将计划进行切分生成多个 stage,stage 内部划分为多个 task, 通过 scheduler 将多个 task 分发到不同的 worker 上执行。由于Presto 本身不存储数据,需要通过多个connector 来访问不同数据源的数据。

B站基于缓存优化 PRESTO 集群查询性能_第4张图片

 

--

03/Presto 改造

我们对 Presto 做的改造主要从可用性、稳定性和性能提升三个角度出发。

 

Presto在B站的实践:https://mp.weixin.qq.com/s/9_lSIFSw5o8sFC8foEtA7w

1. 可用性改进

① Presto 和 hive 语法之间兼容性的操作

② Hive Ranger Plugin 的兼容

在 Ranger 社区中,不同的引擎有不同的 policy 进行管理,我们使用了hive 的 policy 来统一进行管理。

2. 稳定性改进

① Coordinator 的多活改造

Presto 的主从架构存在单点故障的问题,也就是当 Coordinator 发生故障的时候会影响到整个集群的查询。多活改造保证了当某一个 Coordinator 发生故障的时候,另一个 Coordinator 会继续对外进行服务。此外,多活也可以减轻单台 Coordinator 的作业压力。

② label 改造

由于多个部门同时使用 Presto 集群进行查询,其中有一些部门对于作业的实时性要求比较高,有些部门会提交查询数据量较大的 query 语句,这就会导致大 query 挤压 Presto 的查询性能,使实时性要求高的查询无法完成。因此我们对 worker 进行了标签的改造,同时在用户提交任务时也给任务打上标签,这样 scheduler 在分发任务的时候就会根据任务标签和 worker 标签将任务分配到相应的 worker 上去执行。

③ 实时惩罚

label 改造实现了不同部门之间 worker 资源的隔离,但对于同一个部门不同的业务还是会存在大 query 挤压资源的现象。因此我们引进实时惩罚策略,对于提交的大语句判断对应的 resource group 并分配 CPU 的阈值。如果超过阈值,Presto worker 会进行 split 并下发惩罚信息暂停执行,等整体 resource group 资源占用量低于阈值后再恢复调度。

④ 查询限制

在 presto Gateway 对 bad sql 进行拦截。包括短时间内重复提交、查询HDFS 数据量较大(超过 30TB)的查询语句。

3. 性能提升

性能提升主要围绕 Presto 缓存来进行,缓存有三部分,分别为数据源/元数据/结果集的缓存。

--

04/Presto on Alluxio

前面几章主要讲解了我们内部对 presto 的改造,接下来介绍 presto 对数据源和元数据的缓存。首先是对于 Alluxio 做缓存的介绍。

1. 背景介绍 — Presto 痛点

① 计算存储分离架构带来网络开销

和传统的 MySQL(存算一体)的数据库不同,Presto 是一个存算分离的数据库。Presto 本身只做计算不做存储,它通过多个 connector 实现远端获取数据,也可以实现联邦查询。但从远端获取数据必然会带来网络上的性能开销。

② 容易受慢 rpc (Remote Procedure Call) 或热 dn 影响,查询性能不稳定

我们 Presto 主要的场景是查询 hive 表为主,需要去底层查询 HDFS 的数据。由下图可见,Presto 查询 HDFS 时每隔一段时间就会有较长时间的慢 rpc 请求,进而导致 Presto 查询性能的不稳定。

B站基于缓存优化 PRESTO 集群查询性能_第5张图片

 

③ 缺少 data locality,性能方面有待提升

2. 背景介绍 — 热数据

上部分从引擎的角度介绍了 Presto 的一些痛点,此部分从业务数据的角度介绍为什么需要 Alluxio 做存储。

下图为对 Presto query 血源信息做的 UI 展示,我们发现有些表/分区存在重复访问的情况,比如图中第一张表的访问热度(tableheat)达到了 866。我们可以对经常被访问的表进行缓存,从而提升 presto 引擎的查询性能。

B站基于缓存优化 PRESTO 集群查询性能_第6张图片

 

3. Alluxio 的引入

① 架构变化

架构上的变化主要有两个,一是对于血缘变化的处理,二是添加了 Alluxio worker。

  • Alluxio worker

原先 Presto worker 直接从 HDFS 访问数据, 现在则是先通过 Alluxio worker 获取数据,如果 Alluxio 中没有对应数据再去最访问 HDFS 获取数据。

  • 增加 Presto 血缘信息解析用于获取热数据

Presto Coordinator 对 sql 进行解析时,会将血缘信息吐到 Kafka 中,再通过消费程序将相应的血缘信息落到数据库中,最后通过自研的血缘分析服务对热数据打上标识。下一次 Coordinator 从 Hive Metastore 访问分区时会判断分区的参数是否有热数据标识,如果有标识,接下来就会走 Alluxio 的逻辑。

B站基于缓存优化 PRESTO 集群查询性能_第7张图片

 

4. Presto on Alluxio 的实现细节

① Alluxio 与 HDFS 的 scheme 不同

当 Presto 去 Hive Metastore 查询的时候,如果想要访问 Alluxio 的数据时,比较简单的做法是将 Hive Metastore 里相应的 scheme 转换为 Alluxio 的 scheme,但这会带来的问题是对于其他的引擎(比如 spark),因为其本来就没有接入 Alluxio,会导致查询不可用。对于这个问题,社区的解决方案是在高版本 Presto 中支持 Alluxio 连接器。原先 Presto 需要通过访问 Hive Metastore 去获取表信息,现在只需要访问 Alluxio 就可以获取信息。Alluxio 内的 SDS 模块有和 Hive Metastore 的通信功能,SDS 模块会在 Alluxio 中将相应的逻辑进行封装,再返还给 Presto 进行处理。

其他互联网公司方案:维护一套新的 Hive Metastore 来用于 adhoc 的场景,并定期将新 HMS 和原先的 HMS 保持同步。同时依靠自己开发的白名单来确定哪些表是需要 Alluxio 缓存的。

由于:

  • 维护一套新的 HMS 运维成本太高
  • 我们希望通过自己的方式来掌管需要把哪些表存到 Alluxio 中

所以我们团队没有使用上述两种方案,而是通过打 Tag 的方式来控制哪些表走 Alluxio。我们的解决方案:改造 hive connector。因为我们需要通过 hive connector 来获取 HMS 中的 parameter 信息,再通过识别分区参数里面 Alluxio 的 tag 来判断是否走 Alluxio 的逻辑并且通过代码将 scheme 替换成 Alluxio 的 scheme。

B站基于缓存优化 PRESTO 集群查询性能_第8张图片

 

② Alluxio 缓存数据的确定

  • 热数据 tag 设置

由于 Alluxio 缓存空间的有限性,没有必要将所有数据进行缓存,因此我们会对热数据打上标识,只把热数据存储到 Alluxio 上。首先,在 Presto 端把 Presto query 血缘信息吐到 Kafka上,再通过 Kafka 消费程序分析血缘信息并落到 Tidb 上。血缘信息主要包括 query 语句,涉及到的 queryid 以及查询表和分区。接下来通过缓存策略服务判断数据热度,并对热度高的数据打上 tag。

  • 缓存策略

访问热度判断:计算表一周平均访问次数,再根据全量表一周内的被访问频率确定划分阈值,高于阈值的为热表。

计算 TTL(离当前最远的热分区的时间跨度)数据:使用滑动窗口的方式实现对离当前时间点最近的热分区的时间跨度计算,在 Alluxio 中剔除超过最远时间点热度分区并将最近 logdate 的分区添加进缓存中。

 

③ 数据一致性保证

当底层 HDFS 数据发生变更的时候,Alluxio 中便可能出现缓存了旧数据和脏数据的情况。针对这一问题,社区普遍的解决方案是通过配置参数达到和 HDFS 的元数据同步。但我们实践过程中由于存在慢 rpc 的情况,所以无法使用社区的解决方案。为此我们自己开发了一套缓存失效服务来监听 Hive Meta Event,当监听到 alter partition 或者 drop partition 的事件时,服务会自动剔除 Alluxio 中存在的相应分区。同时,我们也会监听 add partition事件。当 add partition 事件并且表的热度较高时,我们也会将相应分区缓存入 Alluxio。下面是 Presto on Alluxio 和 Presto on HDFS 的性能对比,查询 Alluxio 对比查询 HDFS 大概可以节省 20% 的查询时间。

B站基于缓存优化 PRESTO 集群查询性能_第9张图片

 

④ Presto on Alluxio 线上效果

目前大约 30% 的 BI 业务已接入到 Alluxio 的缓存中,已缓存 20w 分区(约45TB)。改造后 Presto 读 HDFS 的稳定性有大幅提升,基本控制在 2.5ms 以内。

B站基于缓存优化 PRESTO 集群查询性能_第10张图片

 

⑤ Presto on Alluxio 线上故障

问题:RocksDB 做元数据存储的时候,线上 Master 进程偶发 crash。

主要背景:Alluxio 原本是放在容器中的,Alluxio 主进程突然发生 crash,拉起 Alluxio 容器后出现了日志丢失的问题。

为了排查 crash 原因,我们将 Alluxio 部署到物理机上,在物理机上通过添加一些 JVM 的参数,等待问题的再次发生。

下图为 JVM 崩溃时打印出来的错误日志,整个异常栈的调用过程为 client 端向 Alluxio 发请求获取文件状态时,会通过 Rocksdb getlocation,再通过 blockid 获得其对应的信息。在操作的过程中,rocks object 对象发生了 GC 被 JVM 回收了,但 rockesdb 是 c++ 的 jni 里面还有该引用,所以会产生 segment fault, 内存地址越界,最后导致了 JVM 的崩溃。此问题已经在社区中有了相应的修复。具体可见以下链接:

https://github.com/Alluxio/alluxio/pull/14856

https://groups.google.com/g/rocksdb/c/PwapmWw

 

--

05/Presto on Local Cache

1. RaptorX 背景

由于 Presto 在执行计划阶段需要访问 HMS 获取表和分区的信息,而HMS 的响应受单点 mysql 的吞吐影响,存在慢查询。

Presto 在构建 split 以及读数据的情况下需要访问 HDFS。HDFS 作为底层存储对接了许多计算引擎,如 Hive、spark 等,在 RPC 请求稳定性方面经常存在 slow rpc,在读 datanode 数据时,存在 slow dn。因此 RaptorX 应运而生,它通过对元数据与数据源进行全方面缓存来解决上述问题。

B站基于缓存优化 PRESTO 集群查询性能_第11张图片

 

图:presto 执行阶段

2. RaptorX 功能介绍

  • Hive Meta Cache

在 Presto 端的 Coordinator 侧对 hive 端的 meta 信息做了缓存,但是考虑到元数据会出现变更,于是我们添加了版本号。每次请求元数据时,我们会将版本号和 HMS 中的版本号做匹配,判断缓存的是否是一个新的 hive meta 数据。

  • File List Cache

在 Presto 的 coordinator 侧对 HDFS 的元数据做一些缓存,避免长时间的 list status 操作。

  • Fragment Result Cache

在 Presto worker 节点对部分查询结果做缓存,避免重复计算。

  • Orc/Parquet Footer Cache

对 orc 或者 parquet 格式的文件的 foote r做缓存,提升 presto 查询的性能。

  • Alluxio Data Cache
  • Soft Affinity scheduling

B站基于缓存优化 PRESTO 集群查询性能_第12张图片

 

Raptorx 相关文章:https://prestodb.io/blog/2021/02/04/raptorx

3. Presto Local Cache-Alluxio Local 模式

在 local 模式中,我们把 Alluxio 通过架构的形式嵌入到 Presto worker的进程中,对 Presto 集群进行统一的管理。这种模式相对于 Presto on Alluxio 来说更加轻量以及便于维护。

B站基于缓存优化 PRESTO 集群查询性能_第13张图片

 

4. Presto Local Cache-Soft Affinity scheduling

搭配 Alluxio Data Cache 使用,它可以使同一个 split 尽可能分发到同一个 worker 节点,保证缓存的命中率。

实现方式有两种,第一种是基于 Hash & Mod,第二种是基于一致性 Hash。

Hash & Mod 是通过 Hash 计算,把 split 分发到对应的 worker 节点。它的缺陷是当 worker 节点数发生变动时(如故障等),总的 worker 节点数就会发生变化,会导致 split 重新分发到别的 worker 节点。

一致性 hash 就是为了解决这个问题而提出的,其基本思路是通过一个哈希环(0-max(value)),首先将 Presto worker 给 Hash 到这个哈希环上,然后再将 split 哈希到环上。在选定方向后,在环上离 split 最近的一个 worker 会对 split 进行处理。这么做的好处是当 Presto worker 发生故障的时候,只有原先分发到这个 worker 的 split 才会重新分发到别的节点处进行执行,此外还有一点优化,单台 worker 可能会出现负载较高的情况,因此我们对一致性 Hash 提出了虚拟节点的概念。比如将一台 worker 映射到三台 worker 分配到哈希环上,再重新进行 split 的分发,这样可以做到 split 更加均匀的分发到不同的 worker 节点上。

B站基于缓存优化 PRESTO 集群查询性能_第14张图片

 

5. Presto Local Cache – Alluxio Cluster

B站基于缓存优化 PRESTO 集群查询性能_第15张图片

 

6. Presto Local Cache – Local vs Cluster

接下来我们看 presto on local cache 和 presto on alluxio cluster 的区别。

Local 是以 jar 包的形式嵌入到 presto 的进程中,cluster 则是需要维护一套 Alluxio 集群,因此 cluster 的运维成本更高。

第二点是缓存的粒度不同,local 缓存粒度更加细,做到了 page 级别的缓存,cluster 是做文件级别的缓存。

第三点是 local 离计算节点资源更近,而 cluster 需要额外的计算机器资源来部署 Alluxio 集群。

B站基于缓存优化 PRESTO 集群查询性能_第16张图片

 

7. Presto Local Cache – 改造点

  • Local cache 与底层数据一致性(presto 端改造)

当底层 hdfs 文件发生变动时,Alluxio 中缓存的可能是旧的数据。这时候Presto 引擎查询时,返回的可能是不准确的脏数据。改造的思路是基于文件的 LastModifiedTime(最后更改时间)来判断,对 Presto 来说最初是获取 HDFS 的元数据文件时同时获取,然后将相应的信息封装到 split 中,Presto 通过 scheduler 将相应的 split 调度到 Presto worker 节点,在节点处将相关的信息封装到HiveFileContext 中。在具体构建 pagesource 时,将 HiveFileContext 传到本地文件系统中。核心方法是openFile,它不同于传统方法直接传一个 path 路径,openFile 方法是传一个 HiveFileContext,因此它不是一个标准的 hadoop api。openFile 会通过 HiveFileContext 来判断是否走 Alluxio。

HiveFileContext 的核心参数有:

(1)cacheable:搭配前文提到的 soft affinixity scheduling 使用,当一台worker 的负载达到上限,不得不调度到其他 worker 进行执行时,由于这台 worker 只是临时支援的,我们会将 cacheable 置 false。

(2)ModificationTime:用于在 Alluxio 中判断缓存的是否是新的数据。

B站基于缓存优化 PRESTO 集群查询性能_第17张图片

 

  • Local cache 与底层数据一致性(Alluxio 端改造)

Alluxio 端改造:

(1)当 presto 去底层读取数据时,通过 localcache.manage.get 得到对应的 page,这时我们需要通过比较文件的 LastModifiedTime 和 Alluxio 内存文件中的 LastModifiedTime 来判断文件是否一致。

(2)构建内存数据结构来保存文件以及时间信息

(3)持久化信息(可用于在 restore 中恢复)

(4)修改 disk 的存储路径以及结构

8. Presto Local Cache – Local Cache 启动问题

(1)Local Cache restore 时间点

Local cache 会去指定的 path 路径加载 page,当 page 较多时就会出现加载耗时高的情况。如下图所示,get file system 时,我们会在 AlluxioCachingFileSystem 创建 local cache,再对 localcache 进行异步加载。但对于 Presto worker 来说,它第一次 get file system 是在 get split 的时候。这种时候可能 local cache 还没有异步加载完毕,此时便会导致缓存命中率的下降。对此进行的改造是:在 Presto worker 启动时,构建一个空路径,通过空路径构建一个 getfilesystem,同步对 local file 进行加载,然后再对外提供服务。

(2)Local Cache 加载失败

local cache 主要是写在 SSD 盘上,可能会遇到磁盘损坏,或者我们先添加一个新 path 路径用于存储 page。但我们新添加的 path 路径对应的 SSD 可能存在磁盘容量身偏高的场景,于是我们设置了一个 local cache 的开关,在以上情况发生时会将 local cache 的开关关闭。

B站基于缓存优化 PRESTO 集群查询性能_第18张图片

 

 

9. Presto Local Cache – Local Cache 支持 HDFS 文件系统

社区对 local cache 实现的 scheme 要求为 Alluxio 和 ws 的 scheme,但我们的线上生产环境主要数据还是以 HDFS 为主,以 Alluxio 为辅。因此我们对 Alluxio 代码做了一些改造,使其能够支持 hdfs 和 viewfs 的scheme。

10. Presto Local Cache — Local Cache 支持多磁盘

背景:单磁盘空间不足且 io 存在限制。

社区解决方法:通过 Hash&Mod 写入多磁盘,这种方法的缺陷是没有考虑到每个磁盘本身容量的情况。

我们的改造:借鉴 HDFS,基于 AvailableSpace 来做磁盘选择。基本思路是对多块磁盘给到一个阈值,超过这个阈值的就认为是容量比较高的,将其放到一个高容量的 list 中,反之亦然。然后给一个概率值,比如 0.75 的概率写到高容量磁盘,0.25 的概率写到低容量磁盘。为什么不直接把数据优先写入高容量磁盘呢,原因有二:

(1)磁盘容量只是其中一个考量因素,不能单纯根据容量高就优先写;

(2)假设线上把所有 page 都写入磁盘容量比较高的盘里面,会造成这个盘的 io 压力过大的情况。

11. Presto Local Cache – Local Cache 测试效果

单并发场景下开启 local cache 缓存可以减少 20% 左右的查询时间,大大提升了查询效率。四并发场景下测试查询时间有一定提升,但相比单并发场景下,性能有一定的损失。

B站基于缓存优化 PRESTO 集群查询性能_第19张图片

 

12. Presto Local Cache — Local Cache 线上效果

目前上线了 3 个 presto 集群,缓存命中率约 40%。

13. Presto Local Cache — 社区 PR

  • Get raw filesystem should consider CachingFileSystem

(https://github.com/prestodb/presto/pull/17390, Merged)

  • Wrapper the input and output stream of HadoopExtendedFileSystem

(https://github.com/prestodb/presto/pull/17365, Merged)

  • Adapt disable filesystem cache

(https://github.com/prestodb/presto/pull/17367, Open)

  • Support hdfs and viewfs as the external filesystem

(https://github.com/Alluxio/alluxio/pull/15131, Closed)

  • Support timely invalidation of parquet metadata cache

(https://github.com/prestodb/presto/pull/17500, Merged)

--

06/后续工作

1. 推广 local 模式上线多个集群

相对于 Presto on Alluxio, local cache 更加稳定也更加轻量。于是我们后续将继续推广 Local 模式。

2. 开发支持 textFile 格式的缓存

社区实现只支持 orc、parquet、rcFile,但线上有很多表用的是 textFile 的格式,所以我们需要开发 textFile 的缓存。

3. 开发磁盘检测

线上的一些 Presto 节点会存在慢节点的情况,需要对有问题的节点进行隔离。

4. 改进 Soft-Affinity

原先 soft affinity 会将同一个文件的 split 分发到同一个节点,会造成单台worker 节点压力比较大的情况,后续计划使用 path+start 作为 key 来哈希,分散大文件分到单个 worker split 的压力。

5. 改进 soft-affinity 排除不开启 cache 的节点

对于没有 local cache 的 presto worker 进行排除。

--

07/问答环节

Q1:presto 跨机房是如何实现的?

A1:由于业务发展,原本在一个 idc 机房的机位已经达到上限,需要开辟新的机房来存储数据。在新机房部署 Hadoop 和 Presto 集群,大家比较容易想到的跨机房难点是资源紧张,因此我们设计了一套 Presto 跨机房的功能。内部是通过用户作业提交到 Presto Getaway,再由 Presto Getaway 分发到不同集群,对 Presto Getaway 进行改造:

1. 分析 sql 语句,看是查询了哪些表和分区,然后对 nnproxy 做了改造,看这些表和分区在哪个机房下,数据量有多少,然后 Presto Getaway 会根据以上信息判断这条 sql 语句会路由到哪个集群执行。比如如果用户提交来的 query 涉及到很多个表,首先对涉及到的表进行分析,最后调度到占数据量最大的机房执行。

2. 此外还有一些优化工作。我们知道有个概念叫做移动数据不如移动计算,原先通过 hive connector 去访问数据的话会出现带宽资源比较紧张的现象,因此我们做了一个计算的下推。主要是实现了一个叫 IDC connector 的连接器。我们可以将第二个机房看作是一个 connector,将跨机房的相应逻辑抛到第二个机房的 presto coordinator 进行处理。IDC2 的 Presto coordinator 获取底层 HDFS 的数据并处理完成后会将结果返还给第一个机房做一个结果合并。此外我们还使用了 Alluxio 来缓存跨机房的数据,比如我们的 query 语句被推到 IDC1 机房进行执行,但很多数据需要通过 IDC2 获取,这时 Alluxio 可以将热度较高的数据跨机房进行缓存,下次就只需要通过 Alluxio 来进行跨机房数据的获取。这两个方法的好处都是可以减少跨机房的流量压力。

Q2:Local Cache 需要部署集群服务吗?

A2:不需要。对于 Alluxio 集群模式需要单独部署 Alluxio 集群,然后 presto 访问 Alluxio 集群。但如果使用 presto local cache 则不需要部署 alluxio 集群,Alluxio 是通过 jar 包的形式嵌入 presto 的进程中,它跟原先的 presto cluster 是共用同一套 presto 集群的,因此相对于 presto on alluxio 来说它会更加的轻量级。

Q3:怎么统计缓存命中率?

A3:社区实现主要是对 worker 端的 metrics进行统计,单台 worker 在生产环境中的命中率达到了 90% 以上。我们自己更加关注 coordinator 端的命中率。前面有提到 hive connector 读取 HMS 中 split 的信息时会带上参数来判断是否走 Alluxio,我们会统计 query 走 Alluxio 的次数,除以整个 presto 集群 query 的次数来得到缓存命中率。目前线上的缓存命中率基本可以达到 40% 左右。

Q4:怎么解决 local cache 的高并发性能问题?

A4:在我们的实验环境中。四并发查询的响应时间明显不如单并发,原因可能是因为数据存在 SSD 盘上,在多次读数据的时候存在磁盘 io 的限制。

Q5:local cache 的内存占用大概是多少?

A5:我们发现存相同大小的文件,local cache 的内存占用相对较低。这是因为 cluster 是基于文件级别存储的,并且当别的 Alluxio worker 参加执行时,别的 worker 也会缓存对应文件。对 local cache 来说,首先是缓存粒度更细(基于 page),只会精准缓存某些 page。另外是 soft affinity scheduling 的策略,它会尽可能将文件对应的 split 分发到 worker 执行。就算遇到单 worker 负载高,分发到其他的 worker 上进行执行的情况时,我们也会通过把 cacheable 参数置 false,让临时 worker 不缓存文件。

今天的分享就到这里,谢谢大家。


分享嘉宾

B站基于缓存优化 PRESTO 集群查询性能_第20张图片

杨洋|bilibili 大数据开发工程师

2021年加入B站工作至今,主要负责Presto与Alluxio相关的研发工作。包括内核研发、线上问题诊断、集群稳定性保障、社区新特性引入及内部特性贡献社区。大数据开源社区爱好者。


你可能感兴趣的:(多维分析,DataFunTalk原创精选,hadoop,大数据,数据分析)