转载自 Apache Kylin 公众号 (作者也是我):原文链接,该文章是 2020 年 4 月 18 号 Kylin on Parquet 介绍及疾速上手线上 meepup 分享的总结文章。
因为 Kylin on Parquet 目前还在不停地迭代倒退,所以此处也对原文中的局部中央做一下更新。
- 在构建局部讲到的 CountDistinct, TopN, Percentile,这些度量目前曾经都反对了,详情请见 KYLIN-4462。
- 补充了主动重试局部 PPT 页
- 构建局部性能数据是我的项目比拟晚期收集,最近又有了更新更具体的比照介绍,详情请见《去 HBase,Kylin on Parquet 性能体现如何?》
前言
Apache Kylin on Apache HBase 计划通过长时间的倒退曾经比拟成熟,然而存在着肯定的局限性。Kylin 查问节点以后次要的计算是在单机节点实现的,存在单点问题。而且因为 HBase 非真正列存的问题,Cuboids 信息须要压缩编码,读取 HBase 数据的时候再反序列化、宰割,额定减少了计算压力。另外,HBase 运维难度比拟大,不便于上云。面对以上问题,Kyligence 推出了 Kylin on Parquet 计划。下文中,Kyligence 的大数据研发工程师王汝鹏解说了 Kylin on Parquet 解决方案的架构、原理以及如何开发调试代码。
本文次要包含以下几方面的内容:首先会给大家介绍架构设计,而后阐明一下咱们为什么会去做 Kylin on Parquet,接下来会介绍一下全新的构建和查问引擎以及相比拟于 Kylin 3.0 的性能体现,最初有一个现场演示 Demo,给大家介绍一下产品的应用和代码调试办法。
架构
Apache Kylin 很早就被设计成了可插拔的架构,基于这种架构咱们就能够很不便的去替换某个模块而不会影响其余模块。
Kylin on Parquet 也是在 Kylin 原来架构的根底上实现了新的查问、构建引擎和存储模块。通过 Spark 实现的查问引擎,可能提交计算工作到 Yarn 上,实现分布式的解决。
Cube 构建这边也是齐全通过 Spark 进行解决,不再反对 MapReduce 构建。
数据源当初反对 Hive 和本地 CSV 数据源,目前能够解脱沙箱的限度,通过本地的 CSV 数据源搭建一个调试环境。
存储层去掉了 HBase,最终构建实现的 Cube 数据都是通过 Parquet 的模式间接存储在文件系统中。
为什么是 Kylin on Parquet?
首先,原来 Kylin 依赖 HBase 的架构在查问的时候会存在单点问题,因为一次查问工作在通过 Coprocessor 获取到数据之后的解决是在查问结点单机上实现的。
HBase 不是一个真正的列式存储,它通过 RowKey 来保留每一行的数据,之所以称之为“列式”,是因为它通过列族的构造治理列数据,何为真正列式存储,能够通过上面文章理解更多:https://en.wikipedia.org/wiki…。
咱们能够看到上面 Cube 逻辑视图中,Kylin 3.0 及以前对于 Cube 是通过将所有的维度和度量别离压缩成一列进行存储的,这样在查问的时候还须要对这一列进行反序列化、宰割等操作,额定减少了计算压力。
最初,HBase 比拟难于保护,运维难度比拟高。
查问过程次要就是 Calcite 会将 SQL 解析成一棵物理执行打算树,其中的计算逻辑的代码都是通过 Calcite 生成的,这些代码会比拟难于调试和定位问题。
Kylin on Parquet 目前可能通过 Spark 进行分布式的查问,咱们对 Calcite 生成的执行打算做了一层转换,转换成了 Spark 的执行打算,其中每一层的解决的数据咱们都是可能通过增加断点查看的。
当初查问相干的逻辑代码也是比拟不便调试的,比方咱们狐疑在聚合 (Agg) 这一层出了问题,咱们就能够在 Agg 这一步增加断点,查看一下数据是不是合乎咱们的冀望。
存储这边咱们替换成了 Parquet,所有的维度和度量会依照每一列进行存储,前面对于存储的构造也会有更加具体的介绍。
Cube 构建与查问
构建引擎
接下来给大家介绍一下全新的构建引擎以及其中的性能是怎么实现的。
- 要害个性
以下是要害的个性:
- 构建引擎齐全的通过 Spark 进行解决,两头的所有流程都可能在 SparkUI 上监控到。如果构建过程呈现了问题,也可能在 SparkUI 上查看工作的执行状况。
- 构建引擎退出了主动调参的性能,这个次要是针对用户没有手动去配置 Spark 参数的状况下,依据构建任务量的状况去调整 Spark 相干的参数,这样能更高效地去执行工作。
- 构建引擎实现了全局字典的分布式构建。
- 退出了主动复原失败工作的性能,当工作失败之后,构建引擎会剖析当前任务失败的起因,而后依据不同失败的状况执行不同解决的策略。
- 接口设计
分享的结尾里,我提到了 Kylin 可插拔式的架构设计,所以下层实现的接口从 AbstractExecutable 到 CubingJob 都是 Kylin 原有的接口,通过调用 SparkCubingJob 的 create 办法能够提交一个构建 Segment 的工作,而后接下来咱们形象进去了两个步骤,一是资源探测,二是构建 Cube。这两步前面也会进行更加具体的介绍。最初,这两步会串联起来通过 Spark 工作的形式提交到集群或者本地去执行。
- 步骤
构建步骤包含资源探测和 Cube 构建。资源探测次要做了三件事,首先它会去估算一下以后数据源表的大小,这里也是为了接下来第二步主动调参筹备的,第三点是构建全局字典。
Cube 构建这一步其实和原来的构建引擎整体步骤是差不多的,首先会通过 Spark 创立平表,而后逐层地构建 Cube,接下来通过 Parquet 的模式进行存储,最初再更新一下 Metadata。为什么咱们会把这么多解决汇合成一个步骤,次要是因为数据次要是通过 Spark 在内存中进行解决,如果再拆分成多步,还须要对两头数据进行长久化等操作,这样解决效率就会打折扣。右图是构建工作在前端的执行状况。
- 主动调参
主动调参性能默认是关上的,并且只在集群模式下失效,而且手动配置的优先级要高于主动调整。它会依据数据源的大小等状况,估算一下以后构建工作须要的计算资源,最终调整 Spark 工作中 executor 相干的参数。
- 全局字典
全局字典性能绝对于 Kylin 3.0 次要有两点晋升:可能分布式地解决;不再局限于整数类型最大值的限度。其实以后 Kylin 3.0 是新退出了分布式构建字典的性能的,不过默认还是单机构建的形式。
具体步骤如下:
- 通过 Spark 创立平表和获取对应列的 distinct 值
- 将数据调配到多个桶中
- 对每一个桶内的数据进行编码
- 保留字典文件和 metadata 数据(桶数量和桶的 offset 值)
第一次构建字典的时候会对每个桶内的值从 1 开始编码,在编码实现后再依据每个桶的 offset 值进行一次整体字典值的调配。
第二次提交 Segment 构建工作的时候,会对每个桶的值进行一次再调配,绝对于桶内已有值进行编码,而后依据新的 offset 去更新每个桶内绝对于全局的一个字典值。
磁盘上保留的目录构造如图所示。
- 主动重试
主动重试性能会剖析导致构建工作失败的异样或谬误,并别离采取不同的解决策略。
- 当遇到 OutOfMemoryError 的时候,引擎会查看以后 Spark 工作是否开启了 AUTO_BROADCASTJOIN_THRESHOLD 这个参数,这个性能比拟容易导致 Spark 工作呈现内存不足的报错,尝试禁用这个性能,而后从新提交构建工作。
- 如果遇到的是 ClassNotFoundException,构建引擎会间接终止当前任务并抛出异样。
- 对于其余异样,构建引擎会尝试调整 executor core 的数量和分配内存大小,而后从新提交工作。
此性能的默认重试次数为三次,而且是默认关上的,如果想禁用此性能,能够将 kylin.engine.max-retry-time 设置为 0 或者如任意正数。
- 度量
构建过程对所有的度量都是会做解决的,具体解决逻辑能够在 CuboidAggregator.scala 文件中查看。因为当初查问引擎还存在一些兼容性的问题,TopN, CountDistinct, Percentile 当初还查不了,然而曾经有 issue 在做了。(补充:以上度量在最新版本的 Kylin on Parquet 曾经全副反对了)
- Parquet 存储
假如咱们最终生成的 cuboid 内容如上图所示,存在三个维度和两个度量,对应的 parquet 文件的 schema 就是两头这张图的样子。咱们会将所维度名称映射成一个惟一的数字,这样也是为了进一步优化存储。咱们能够将 parquet 文件下载到本地,通过 spark 看到以后 parquet 文件,也就是咱们保留的 cuboid 文件的 schema 内容。
磁盘上存储的目录构造如上图所示,所有文件是通过我的项目来归类的,包含字典,构建产生的临时文件以及构建实现的所有 cuboids。Segment 目录会有一个独立的签名,防止出现写入抵触等问题。
- 性能比照
咱们将新的构建引擎和 Kylin 3.0 的构建引擎(MapReduce)做了一下比照,运行环境是领有四个计算节点,Yarn 领有 400G 内存和 128 内核的集群。Spark 应用的外部版本,因为咱们对 Spark 源码做了一些优化,所以目前并不反对社区版 Spark。测试的数据集是规范的 SSB 数据集。
右边是最终占用存储空间的大小,新构建引擎存储空间占用可能缩小一半。左边是构建工夫的比照,也可能看到新构建引擎也比 Kylin 3.0 快了许多。
查问引擎
- 步骤
一次查问的申请收回后,Calcite 会剖析 SQL 并解析成形象语法树 (AST),而后对 AST 进行校验、优化等操作后,再转换成执行打算树(RelNodes)。新查问引擎会将所有的 RelNodes 转换成 Spark 执行打算。最初再通过 Spark 去执行所有的查问工作。
查问引擎会把每一个计算逻辑转换成对应的 Spark 逻辑。转换的这一步其实也做了不少工作,因为 Calcite 有本人的类型,Spark 也有本人的类型,咱们须要对其进行解决。Calcite 的一些函数操作也须要做一些对应的实现。
开始的时候也说过了,咱们能够在每一个 DataFrame 中增加断点去进行调试,查问两头解决的值,这样可能更加不便的排查问题。查问引擎会在第一次收到查问申请的时候在 Yarn 上创立一个常驻过程,专门用来解决查问工作。
针对查问引擎还做了依赖隔离的解决,次要避免内部依赖类抵触的问题。
- 性能比照
查问引擎的性能体现也是和 Kylin 3.0 做了一下比照,测试环境和构建性能测试环境是一样的,这里就不赘述了。咱们对 SSB 数据集和 TPCH 数据集都做了比照。
SSB 数据集规模大略有六千万行,不过 SSB 的规范 SQL 大都比较简单,所有咱们看到查问基本上都是一秒内实现的。
TPCH 数据集规模大略有一千两百万行,TPCH 的规范 SQL 要求更高一些,咱们能够看到 Kylin3.0 耗时十分长的查问工作,新的构建引擎的查问可能快很多,因为咱们对简单的查问做了一些优化。
Demo 演示
请点击播放下方链接现场回顾视频,拖动进度条至 26:35 的地位,即可开始观看。
Demo 演示视频