vlambda博客
学习文章列表

kylin—分布式的分析型数据仓库

kylin—分布式的分析型数据仓库

This browser does not support music or audio playback. Please play it in WeChat or another browser. kylin—分布式的分析型数据仓库

  • Kylin定义
  • Kylin特点
  • Kylin架构
  • Kylin工作原理
  •     维度和度量
  •     Cube和Cuboid
  •      核心算法
                  逐层构建算法
                  快速构建算法

Kylin定义
Apache Kylin是一个开源的分布式分析引擎,提供Hadoop/Spark之上的SQL查询接口及多维分析(OLAP)能力以支持超大规模数据,最初由eBay Inc开发并贡献至开源社区。 它能在亚秒内查询巨大的Hive表。

Kylin特点
Kylin的主要特点包括支持SQL接口、支持超大规模数据集、亚秒级响应、可伸缩性、高吞吐率、BI工具集成等。
1)标准SQL接口: Kylin是以标准的SQL作为对外服务的接口。
2)支持超大数据集: Kylin对于大数据的支撑能力可能是目前所有技术中最为领先的。 早在2015年eBay的生产环境中就能支持百亿记录的秒级查询,之后在移动的应用场景中又有了千亿记录秒级查询的案例。
3)亚秒级响应: Kylin拥有优异的查询相应速度,这点得益于预计算,很多复杂的计算,比如连接、聚合,在离线的预计算过程中就已经完成,这大大降低了查询时刻所需的计算量,提高了响应速度。
4)可伸缩性和高吞吐率: 单节点Kylin可实现每秒70个查询,还可以搭建Kylin的集群。
5)BI工具集成
Kylin可以与现有的BI工具集成,具体包括如下内容。
ODBC: 与Tableau、Excel、PowerBI等工具集成
JDBC: 与Saiku、BIRT等Java工具集成
RestAPI: 与JavaScript、Web网页集成
Kylin开发团队还贡献了Zepplin的插件,也可以使用Zepplin来访问Kylin服务。

Kylin架构
kylin—分布式的分析型数据仓库
1)REST Server
REST Server是一套面向应用程序开发的入口点,旨在实现针对Kylin平台的应用开发工作。 此类应用程序可以提供查询、获取结果、触发Cube构建任务、获取元数据以及获取用户权限等等。 另外可以通过Restful接口实现SQL查询。
2)查询引擎(Query Engine)
当Cube准备就绪后,查询引擎就能够获取并解析用户查询。 它随后会与系统中的其它组件进行交互,从而向用户返回对应的结果。  
3)Routing
负责将解析的SQL生成的执行计划转换成Cube缓存的查询,Cube是通过预计算缓存在hbase中,这部分查询可以在秒级设置毫秒级完成,而且还有一些操作使用过的查询原始数据(存储在Hadoop的HDFS中通过Hive查询)。 这部分查询延迟较高。
4)元数据管理工具(Metadata)
Kylin是一款元数据驱动型应用程序。 元数据管理工具是一大关键性组件,用于对保存在Kylin当中的所有元数据进行管理,其中包括最为重要的Cube元数据。 其它全部组件的正常运作都需以元数据管理工具为基础。 Kylin的元数据存储在hbase中。  
5)任务引擎(Cube Build Engine)
这套引擎的设计目的在于处理所有离线任务,其中包括Shell脚本、Java API以及Map Reduce任务等等。 任务引擎对Kylin当中的全部任务加以管理与协调,从而确保每一项任务都能得到切实执行并解决其间出现的故障。

Kylin工作原理
Apache Kylin的工作原理本质上是MOLAP(Multidimension On-Line Analysis Processing)Cube,也就是多维立方体分析。 是数据分析中非常经典的理论,下面对其做简要介绍。

维度和度量
维度: 即观察数据的角度。 比如员工数据,可以从性别角度来分析,也可以更加细化,从入职时间或者地区的维度来观察。 维度是一组离散的值,比如说性别中的男和女,或者时间维度上的每一个独立的日期。 因此在统计时可以将维度值相同的记录聚合在一起,然后应用聚合函数做累加、平均、最大和最小值等聚合计算。
度量: 即被聚合(观察)的统计值,也就是聚合运算的结果。 比如说员工数据中不同性别员工的人数,又或者说在同一年入职的员工有多少。

Cube和Cuboid
有了维度跟度量,一个数据表或者数据模型上的所有字段就可以分类了,它们要么是维度,要么是度量(可以被聚合)。 于是就有了根据维度和度量做预计算的Cube理论。
给定一个数据模型,我们可以对其上的所有维度进行聚合,对于N个维度来说,组合的所有可能性共有2n种。 对于每一种维度的组合,将度量值做聚合计算,然后将结果保存为一个物化视图,称为Cuboid。 所有维度组合的Cuboid作为一个整体,称为Cube。
下面举一个简单的例子说明,假设有一个电商的销售数据集,其中维度包括时间[time]、商品[item]、地区[location]和供应商[supplier],度量为销售额。 那么所有维度的组合就有24 = 16种,如下图所示:
kylin—分布式的分析型数据仓库
一维度(1D)的组合有: [time]、[item]、[location]和[supplier]4种;
二维度(2D)的组合有: [time, item]、[time, location]、[time, supplier]、[item, location]、[item, supplier]、[location, supplier]3种;
三维度(3D)的组合也有4种;
最后还有零维度(0D)和四维度(4D)各有一种,总共16种。
注意: 每一种维度组合就是一个Cuboid,16个Cuboid整体就是一个Cube。

核心算法
Kylin的工作原理就是对数据模型做Cube预计算,并利用计算的结果加速查询:
1)指定数据模型,定义维度和度量;
2)预计算Cube,计算所有Cuboid并保存为物化视图;
预计算过程是Kylin从Hive中读取原始数据,按照我们选定的维度进行计算,并将结果集保存到Hbase中,默认的计算引擎为MapReduce,可以选择Spark作为计算引擎。 一次build的结果,我们称为一个Segment。 构建过程中会涉及多个Cuboid的创建,具体创建过程由kylin.Cube.algorithm参数决定,参数值可选 auto,layer 和 inmem, 默认值为 auto,即 Kylin 会通过采集数据动态地选择一个算法 (layer or inmem),如果用户很了解 Kylin 和自身的数据、集群,可以直接设置喜欢的算法。
3)执行查询,读取Cuboid,运行,产生查询结果。

逐层构建算法(layer)
我们知道,一个N维的Cube,是由1个N维子立方体、N个(N-1)维子立方体、N*(N-1)/2个(N-2)维子立方体、......、N个1维子立方体和1个0维子立方体构成,总共有2^N个子立方体组成,在逐层算法中,按维度数逐层减少来计算,每个层级的计算(除了第一层,它是从原始数据聚合而来),是基于它上一层级的结果来计算的。 比如,[Group by A, B]的结果,可以基于[Group by A, B, C]的结果,通过去掉C后聚合得来的; 这样可以减少重复计算; 当 0维度Cuboid计算出来的时候,整个Cube的计算也就完成了。
每一轮的计算都是一个MapReduce任务,且串行执行; 一个N维的Cube,至少需要N+1次MapReduce Job。
算法优点:
1)此算法充分利用了MapReduce的能力,处理了中间复杂的排序和洗牌工作,故而算法代码清晰简单,易于维护;
2)受益于Hadoop的日趋成熟,此算法对集群要求低,运行稳定; 在内部维护Kylin的过程中,很少遇到在这几步出错的情况; 即便是在Hadoop集群比较繁忙的时候,任务也能完成。
算法缺点:
1)当Cube有比较多维度的时候,所需要的MapReduce任务也相应增加; 由于Hadoop的任务调度需要耗费额外资源,特别是集群较庞大的时候,反复递交任务造成的额外开销会相当可观;
2)此算法会对Hadoop MapReduce输出较多数据; 虽然已经使用了Combiner来减少从Mapper端到Reducer端的数据传输,所有数据依然需要通过Hadoop MapReduce来排序和组合才能被聚合,无形之中增加了集群的压力;
3)对HDFS的读写操作较多: 由于每一层计算的输出会用做下一层计算的输入,这些Key-Value需要写到HDFS上; 当所有计算都完成后,Kylin还需要额外的一轮任务将这些文件转成HBase的HFile格式,以导入到HBase中去;
总体而言,该算法的效率较低,尤其是当Cube维度数较大的时候。

快速构建算法(inmem)
也被称作“逐段”(By Segment) 或“逐块”(By Split) 算法,从1.5.x开始引入该算法,利用Mapper端计算先完成大部分聚合,再将聚合后的结果交给Reducer,从而降低对网络瓶颈的压力。 该算法的主要思想是,对Mapper所分配的数据块,将它计算成一个完整的小Cube 段(包含所有Cuboid); 每个Mapper将计算完的Cube段输出给Reducer做合并,生成大Cube,也就是最终结果; 如图所示解释了此流程。
与旧算法相比,快速算法主要有两点不同:
1) Mapper会利用内存做预聚合,算出所有组合; Mapper输出的每个Key都是不同的,这样会减少输出到Hadoop MapReduce的数据量;
2)一轮MapReduce便会完成所有层次的计算,减少Hadoop任务的调配。