神兽麒麟kylin驾驭指南

​ 简单介绍一下:Apache Kylin 是一个开源的分布式分析引擎 。Apache 顶级项目之一,国产的,很屌的,神兽,大家都叫他麒麟。支持多维分析,支持超大规模数据,支持亚秒级交互式分析查询,支持高并发…。

1、前言

在介绍kylin之前先介绍下数据处理分类。因为我们神兽Kylin就是ebay开发的一套OLAP系统 。那什么是OLAP呢?

1.1、OLAP和OLTP

数据处理大致可以分成两大类:
联机分析处理OLAP(On-Line Analytical Processing)

①OLAP是数据仓库系统的主要应用,支持复杂的分析操作,侧重决策支持,并且提供直观易懂的查询结果;
②OLAP(On-Line Analytical Processing)在线分析处理是一种共享多维信息的快速分析技术;
③OLAP利用多维数据库技术使用户从不同角度观察数据;
④OLAP用于支持复杂的分析操作,侧重与对管理人员的决策支持,可以满足分析人员的快速、灵活地进行大数据复量的复杂查询的要求、并且以一种直观易懂的形式呈现查询结果,辅助决策。

联机事务处理OLTP(On-Line Transaction Processing)

OLTP是传统的关系数据库的主要应用,主要用于基本的、日常的事务处理。例如银行交易。
OLTP:On-Line Transaction Processing,联机事务处理,表示事务性非常高的系统,一般都是高可用的在线系统。以小的事物和小的查询为主,评测其系统时,一般看每秒执行的Transaction和Execute SQL的数量。在这样的系统中,单个数据库每秒处理的Transaction往往超过几百个、几千个。select语句的执行量每秒几千甚至几万个。典型的OLAP系统有电子上午系统、银行、证券等。在这里我们不做过多介绍,重点放在OLAP处理上。

1.2、OLAP特点

快速性:用户对OLAP的快速反应能力有很高的要求。系统应能在5秒内对用户的大部分分析要求做出反应。
可分析性:OLAP系统应能处理与应用有关的任何逻辑分析和统计分析。
多维性:多维性是OLAP的关键属性。系统必须提供对数据的多维视图和分析,包括对层次维和多重层次维的完全支持。
信息性:不论数据量有多大,也不管数据存储在何处,OLAP系统应能及时获得信息,并且管理大容量信息。

1.3、OLAP分类
1.3.1、按存储方式分类

ROLAP
ROLAP将多维数据库的多维结构划分为两类表:一类是事实表,用来存储数据和维关键字;另一类是维表,即对每个维至少使用一个表来存放维的层次、成员类别等维的描述信息。维表和事实表通过主关键字和外关键字联系在一起,形成了"星型模式"。对于层次复杂的维,为避免冗余数据占用过大的存储空间,可以使用多个表来描述,这种星型模式的扩展称为"雪花模式"。特点是将细节数据保留在关系型数据库的事实表中,聚合后的数据也保存在关系型的数据库中。这种方式查询效率最低,不推荐使用。
MOLAP
表示基于多维数据组织的OLAP实现(Multidimensional OLAP)。以多维数据组织方式为核心,也就是说,MOLAP使用多维数组存储数据。多维数据在存储中将形成"立方块(Cube)“的结构,在MOLAP中对"立方块"的"旋转”、“切块”、"切片"是产生多维数据报表的主要技术。特点是将细节数据和聚合后的数据均保存在cube中,所以以空间换效率,查询时效率高,但生成cube时需要大量的时间和空间。
HOLAP
表示基于混合数据组织的OLAP实现(Hybrid OLAP)。如低层是关系型的,高层是多维矩阵型的。这种方式具有更好的灵活性。特点是将细节数据保留在关系型数据库的事实表中,但是聚合后的数据保存在cube中,聚合时需要比ROLAP更多的时间,查询效率比ROLAP高,但低于MOLAP。

1.3.2、按处理方式分类

Server OLAP:数据在服务器端的多维分析
Client OLAP:把部分数据下载到本地,为用户提供本地的多维分析

1.4、OLAP基本操作

Drill-down:钻取,在维的不同层次间的变化,从上层降到下一层,或者说将汇总数据拆分成更细节的数据。比如第二季度的数据拆分成4、5、6月。
Roll-up:上卷,钻取的逆操作,从下层升到上一层,将更细粒度的数据向高层次进行聚合。比如将一年12个月的数据聚合成四个季度的数据。
Slice:切片,获取数据某一个维上特定值的数据,比如在时间维上,有十二个月,取4月的数据。
Dice:切块,获取数据在某一个维上多个值的数据,比如在时间维上,取3,4,5月的数据,这些数据就是一个块。
Pivot:旋转,维的位置的转换,就像二维表中行列的转换。

2、kylin基本原理

2.1、名词解释
维度
维度是观察数据的角度。观察数据的角度,查询条件。
度量
度量是具体考察的聚合数量值,数据度量的指标,数据的实际含义 ,最终要统计的结果值 。
事实表
事实表(Fact Table)是指存储事实记录的表,如用户行为日志、用户交易订单等等
维度表
维度表(Dimension Table)也称维表或查找表(Loookup Table),如时间维表、地区维表、商品分类维表等
维度基数
维度基数(Cardinality)是指该维度在数据集中出现的不同值的数量。如地区(省市县)是一个维度,总共算下来也就几百个,是低基维;而用户id、手机号、手机设备号会有上千万+甚至是过亿,是高基维(Ultra High Cardinality UHC),如果维度中有多个高基维或超级高基维,那么Cube的膨胀就会很高。
Cube膨胀
简单来说Cube膨胀是由于维度组合产生的数据量比原始数据大出的倍数,如此看来,如果维度有过多的高基维会导致维度组合对应的数据会更多,如用户手机号、年龄、性别作为维度,用户手机号过亿那么对应的年龄、性别二维组合产生的是基于亿级【用户手机号】* 年龄 * 性别的量级
Cube
1 Cube 数据立方体,对原始数据建立多维度索引,采用预计算的方式大大加快数据的查询效率,一般应用为结果为聚合数据类型的实时查询领域
2 Cuboid 数据立方体本质上是在明确的维度和度量场景下,将多个维度按照不同组合方式进行分组产生的度量结果,而其中的任何一种组织方式
3 Cube Segment是Cube计算产生的一个数据片段(如增量Cube,会随着事实表的时间分区来进行Cube的增量构建,而每天产生的Cube底层的数据片段即为Segment)
Cube结果保存
kylin的cube构建结果会保存到hbase之中,由于hbase是kv类型的存储结构,下面简单介绍下cube的hbase保存形式。
1 hbase的rowkey
  kylin使用cube选择的多个维度作为rowkey的一部分,在hbase中保存数据形成以维度的组合以二进制字符串对应的形式,如有sources、area_code,gender作为维度,则101表示以source、gender作为维度组合。
2.2、基本原理和架构

​ 下面开始聊一聊Kylin的基本原理和架构。简单来说,Kylin的核心思想是预计算,即对多维分析可能用到的度量进行预计算,将计算好的结果保存成Cube,供查询时直接访问。也就是用空间换时间,把高复杂度的聚合运算、多表连接等操作转换成对预计算结果的查询,这决定了Kylin能够拥有很好的快速查询和高并发能力。

​ 一个Cube的例子,假设我们有4个维度,这个Cube中每个节点(称作Cuboid)都是这4个维度的不同组合,每个组合定义了一组分析的维度(如group by),measure的聚合结果就保存在这每个Cuboid上。查询时根据SQL找到对应的Cuboid,读取度量的值,即可返回。

​ 为了更好的适应大数据环境,Kylin从数据仓库中最常用的Hive中读取源数据,使用 MapReduce作为Cube构建的引擎,并把预计算结果保存在HBase中,对外暴露Rest API/JDBC/ODBC的查询接口。因为Kylin支持标准的ANSI SQL,所以可以和常用分析工具(如Tableau、Excel等)进行无缝对接。

​ Cubing的算法。简单来说,就是按照维度数量从大到小的顺序,从Base Cuboid开始,依次基于上一层Cuboid的结果进行再聚合。每一层的计算都是一个单独的Map Reduce任务。

​ HBase中每行记录的Rowkey由维度组成,度量会保存在column family中。为了减小存储代价,这里会对维度和度量进行编码。查询阶段,利用HBase列存储的特性就可以保证Kylin有良好的快速响应和高并发。 有了这些预计算的结果,当收到用户的SQL请求,Kylin会对SQL做查询计划,并把本该进行的Join、Sum、Count Distinct等操作改写成Cube的查询操作。 Kylin提供了一个原生的Web界面,在这里,用户可以方便的创建和设置Cube、管控Cube构建进度,并提供SQL查询和基本的结果可视化。

3、Kylin特性

可扩展超快的基于大数据的OLAP引擎: Kylin是为减少在Hadoop/Spark上百亿规模数据查询延迟而设计 。

交互式查询能力: 通过Kylin,用户可以与Hadoop数据进行亚秒级交互,在同样的数据集上提供比Hive更好的性能

实时 OLAP: Kylin可以在数据产生时进行实时处理,用户可以在秒级延迟下进行实时数据的多维分析。

Hadoop ANSI SQL 接口: 作为一个OLAP引擎,Kylin为Hadoop提供标准SQL支持大部分查询功能

多维立方体(MOLAP Cube): 用户能够在Kylin里为百亿以上数据集定义数据模型并构建立方体

与BI工具无缝整合: Kylin提供与BI工具的整合能力,如Tableau,PowerBI/Excel,MSTR,QlikSense,Hue和SuperSet

其他特性:

  • Job管理与监控
  • 压缩与编码
  • 增量更新
  • 利用HBase Coprocessor
  • 基于HyperLogLog的Dinstinc Count近似算法
  • 友好的web界面以管理,监控和使用立方体
  • 项目及表级别的访问控制安全
  • 支持LDAP、SSO

4、cube构建流程

cube构建流程:

(1) 创建临时的HIVE平表
选择数据源形成数据集

​ 首先将数据从数据源Hive库表中选择将要进行多维计算的【事实表Fact Table】(如有需要还要确定【维表 Lookup Table】使用join关联) 提取出来形成一个数据集插入到一个临时表。如果是【增量构建】,则Cube是分区的,Kylin会加上一个时间条件以确保只有在时间范围内的数据才会被提取。可以在这个步骤的log查看相关的Hive命令。

数据源读取时的参数优化

在Hive命令运行时,Kylin会用conf/kylin_hive_conf.properties里的配置,比如保留更少的冗余备份(dfs.replication=2)和启用Hive的mapper side join(hive.auto.convert.join.noconditionaltask=true),需要的话可以根据集群的具体情况增加其他配置。另外可以根据不同的cube进行hive的参数覆盖,具体形式在cube的【参数覆盖】中设置。

kylin.hive.config.override.xxx

如果启用了Hive的文件合并,你可以在conf/kylin_hive_conf.xml里关闭它,因为Kylin有自己合并文件的方法

<property>
    <name>hive.merge.mapfiles</name>
    <value>false</value>
    <description>Disable Hive's auto merge</description>
</property>
全量构建和增量构建

如果cube的分区列(如上示例中的bdp_day)与Hive表的分区列相同,那么根据它过滤数据能让Hive聪明地跳过不匹配的分区。因此强烈建议用Hive的分区列(如果它是日期列)作为cube的分区列。这对于那些数据量很大的表来说几乎是必须的,否则Hive不得不每次在这步扫描全部文件,消耗非常长的时间。

全量构建

对于多维计算模型中没有指定时间列做数据分区的Cube来说,kylin会使用全量构建

增量构建

增量构建是基于某个时间列分区进行数据过滤来进行构建任务的,所以形成的segment对应了一个时间范围,如下图所示。而segment对应的范围采用了前包后闭原则,即包含开始时间但不包含结束时间,这样保证segment总体上不会有重复情况。
segment合并

由于增量构建或流式数据源会产生大量的segment,这样会造成查询性能的下降,另外segmengt对应的hbase的HTable也会增多对hdfs带来影响,这样就有必要对segment进行合并形成较大的segment。

在进行segment合并时kylin会直接对cuboid文件作为输入而不需要从原始数据源中提取(因为维度有对应编码并形成了单独文件)这样重新产生新的segment及对应的HTable后才结束,并将之前的segment及HTable删除。

(2) 重新分发中间表
重发布原因

在之前的一步之后,根据数据的分布情况甚至过滤条件等原因,Hive在HDFS上的目录里生成了数据文件:有些是大文件,有些是小文件甚至空文件。这种不平衡的文件分布会导致之后的MR任务出现数据倾斜的问题:有些mapper完成得很快,但其他的就很慢,所以我们要使用shuffle机制进行重新分发为后续计算提供帮助。

重新分发表的命令:

hive -e "USE default;
SET dfs.replication=2;
SET hive.exec.compress.output=true;
SET hive.auto.convert.join.noconditionaltask=true;
SET hive.auto.convert.join.noconditionaltask.size=100000000;
SET mapreduce.job.split.metainfo.maxsize=-1;
set mapreduce.job.reduces=160;
set hive.merge.mapredfiles=false;
INSERT OVERWRITE TABLE kylin_intermediate_airline_cube_v3610f668a3cdb437e8373c034430f6c34 SELECT * FROM kylin_intermediate_airline_cube_v3610f668a3cdb437e8373c034430f6c34 DISTRIBUTE BY RAND();
"

首先,Kylin通过查询hive数据表计算出中间表的行数,然后基于行数的大小算出重新分发数据需要的文件数。默认情况下,Kylin为每100万行【kylin.job.mapreduce.mapper.input.rows】分配一个文件对应一个reducer,每个reducer会写一个文件,通过设置【mapreduce.job.reduces=N】指定reduce的数量。在接下来对这张表进行的MR步骤里,Hadoop会启动和文件相同数量的mapper来处理数据(通常一百万行数据比一个HDFS数据块要小)。如果你的日常数据量没有这么大或者Hadoop集群有足够的资源,你或许想要更多的并发数,这时可以将conf/kylin.properties里的kylin.job.mapreduce.mapper.input.rows设为小一点的数值,比如:

kylin.job.mapreduce.mapper.input.rows=500000

其次,Kylin会运行 “INSERT OVERWRITE TABLE … DISTRIBUTE BY “ 形式的HiveQL来分发数据到指定数量的reducer上。在很多情况下,Kylin请求Hive随机分发数据到reducer,然后得到大小相近的文件,分发的语是”DISTRIBUTE BY RAND()”。这样既合并了小文件也消除了木桶效应(数据不均导致的任务执行缓慢),而【distribute by rand()】则为下游数据进行了水平分布。

基于高基维的分发

如果你的cube指定了一个高基数的列,比如”USER_ID”,作为分片维度【shard by】(在cube的“高级设置”页面),Kylin会让Hive根据该列的值重新分发数据,那么在该列有着相同值的行将被分发到同一个文件。这比随机要分发要好得多,因为不仅重新分布了数据,并且在没有额外代价的情况下对数据进行了预先分类,如此一来接下来的cube build处理会从中受益。在典型的场景下,这样优化可以减少40%的build时长,分发的语句是”DISTRIBUTE BY USER_ID”。

注意:

(1) “分片”列应该是高基数的维度列,并且它会出现在很多的cuboid中(不只是出现在少数的cuboid)。 使用它来合理进行分发可以在每个时间范围内的数据均匀分布,否则会造成数据倾斜,从而降低build效率。典型的正面例子是:“USER_ID”、“SESSION_ID”、“PRODUCT”等等,这些列的基数应该大于一千(远大于reducer的数量)

(2) ”分片”对cube的存储和查询同样有好处,可以联系到rowkey的形成规则。

(3) 构建维度字典

Kylin会启动一个MR任务来提取各个维度在临时表中的不同值,用于构建维度字典,而每一个采用字典编码的维度,kylin将其不同值抽取到一个单独文件中,对于高基维来说对应的字典会较大,一般不建议对高基维采用字典编码方式,转而根据实际情况使用如“fixed_length”、“integer”等等。

维度编码

维度编码(Encoding)的目的是压缩数据存储空间,提高扫描效率。如地区维度、网页地址等。

编码类型说明备注
字典编码维度值的基数较小且数据量较大时会大大节省空间kylin.dictionary.max.cardinality字典大小
时间编码Date编码|Time编码使用较少的空间存储对应数值
数字编码Integer编码适合对int或bigint类型值编码
定长编码Fixed_length编码设置定长,如身份证UTF-8
维度字典(优缺点)
Dictionary表示需要为这个维度建立字典树。因为每一个维度的dictionary都会保存在内存中,如果字典树占用很大的内存会影响kylin的使用甚至导致OOM,对于dictionary的编码使用的是字典树,它的原理实际上是为每一个维度成员赋予一个整数的id,实际存储的时候存储的是这个id的二进制值(使用int最多占用4个字节),并且保证每一个id的顺序和维度成员的顺序相同的,例如aaa的id=1,aab的id=2,aac的id=3,这样在查询的时候就可以直接根据column>aaa转换成id>1,方便hbase coprocessor的处理。

(4) 保存cuboid的统计数据和创建 HTable
1 将采集的cuboid的统计信息保存到kylin的元数据存储,供后续使用
2 为本次cube构建产生的segment创建HBase table
(5) 构建基础cuboid

cube确立之后基础cuboid就产生了,就是所有维度都参与的组合,如上图4-D base cuboid,这样当kylin采用【layer】逐层构建时,将会已“临时平表”作为数据源先构建base cuboid,然后由基础cuboid来N-1的逐层构建。用Hive的中间表构建基础的cuboid,是“逐层”构建cube算法的第一轮MR计算。Mapper的数目与第二步的reducer数目相等;Reducer的数目是根据cube统计数据估算的:默认情况下每500MB输出使用一个reducer;如果观察到reducer的数量较少,你可以将kylin.properties里的“kylin.job.mapreduce.default.reduce.input.mb”设为小一点的数值以获得过多的资源,比如:

kylin.job.mapreduce.default.reduce.input.mb=200
(6) 构建N维Cuboid

这些步骤是“逐层”构建cube的过程,每一步以前一步的输出作为输入,然后去掉一个维度以聚合得到一个子cuboid。举个例子,cuboid ABCD去掉A得到BCD,去掉B得到ACD。

有些cuboid可以从一个以上的父cuboid聚合得到,这种情况下,Kylin会选择最小的一个父cuboid。举例,AB可以从ABC(id:1110)和ABD(id:1101)生成,则ABD会被选中,因为它的比ABC要小。在这基础上,如果D的基数较小,聚合运算的成本就会比较低。

构建规则

当设计rowkey序列的时候,请记得将基数较小的维度放在末尾。这样不仅有利于cube构建,而且有助于cube查询,因为预聚合也遵循相同的规则。

构建过程

通常来说,从N维到(N/2)维的构建比较慢,因为这是cuboid数量爆炸性增长的阶段:N维有1个cuboid,(N-1)维有N个cuboid,(N-2)维有N*(N-1)个cuboid,以此类推。经过(N/2)维构建的步骤,整个构建任务会逐渐变快。

(7) 构建cube

这个步骤使用一个新的算法来构建cube:“逐片”构建(也称为“内存”构建)。它会使用一轮MR来计算所有的cuboids,但是比通常情况下更耗内存。配置文件”conf/kylin_job_inmem.xml”正是为这步而设。默认情况下它为每个mapper申请3GB内存。如果你的集群有充足的内存,你可以在上述配置文件中分配更多内存给mapper,这样它会用尽可能多的内存来缓存数据以获得更好的性能,比如:

<property>
    <name>mapreduce.map.memory.mb</name>
    <value>6144</value>
    <description></description>
</property>
<property>
    <name>mapreduce.map.java.opts</name>
    <value>-Xmx5632m</value>
    <description></description>
</property>

请注意,Kylin会根据数据分布(从cube的统计数据里获得)自动选择最优的算法,没有被选中的算法对应的步骤会被跳过。你不需要显式地选择构建算法。

(8) 将cuboid数据转换为HFile

这一步启动一个MR任务来讲cuboid文件(序列文件格式)转换为HBase的HFile格式。Kylin通过cube统计数据计算HBase的region数目,默认情况下每5GB数据对应一个region。Region越多,MR使用的reducer也会越多。如果你观察到reducer数目较小且性能较差,你可以将“conf/kylin.properties”里的以下参数设小一点,比如:

kylin.hbase.region.cut=2
kylin.hbase.hfile.size.gb=1
(9) 将HFile导入HBase表

这一步kylin使用HBase API来讲HFile导入region server,这是轻量级并快速的一步。

(10) 更新cube信息

在导入数据到HBase后,Kylin在元数据中将对应的cube segment标记为ready。

(11) 清理资源

将中间宽表从Hive删除。这一步不会阻塞任何操作,因为在前一步segment已经被标记为ready。如果这一步发生错误,不用担心,垃圾回收工作可以晚些再通过Kylin的StorageCleanupJob完成。

5、企业应用

​ 根据公开数据显示,Kylin的查询性能不只是针对个别SQL,而是对上万种SQL 的平均表现,生产环境下90%ile查询能够在在3s内返回。来自美团、京东、百度等互联网公司都在使用。例如,在京东云海的案例中,单个Cube最大有8个维度,最大数据条数4亿,最大存储空间800G,30个Cube共占存储空间4T左右。查询性能上,当QPS在50左右,所有查询平均在200ms以内,当QPS在200左右,平均响应时间在1s以内。

​ 在携程。 Cube 的数量现在稳定在 300 多个,覆盖 7 个业务线,其中最大的业务线是度假玩乐。目前单份数据存储总量是 56 T,考虑到 HDFS 三份拷贝,所以总存储量大约 182 T,数据规模达到 300 亿条左右。最大的 Cube 来自于火车票业务,一天最大的数据是 28 亿,一天次构建最大的结果集在 13 T 左右。查询次数比较固定,基本上是 20 万查询/天,通过 Kylin 的查询日志分析下来,90% 的查询可以达到 300 ms 左右。

6、Apache Kylin v3.0.x新特性

Apache Kylin v3.0.0-alpha 是一次重大更新。3.0.0-alpha 增加了对流式数据源进行实时查询的能力;使用Livy Rest API提交Spark Job,从而免除本地安装Spark客户端配置的麻烦;增加了新的基于Zookeeper的作业调度器。

重要特性包括:

①借助新增加了Receiver集群,Kylin实现了毫秒级别的数据准备延迟,可以实时查询来自Kafka数据源的消息,点击了解关于如何在本地运行

②Spark 作业的提交通过RestAPI来向Livy Server提交,而无需在本地启动Spark Driver进程,从而方便对Spark资源的管理监控,同时也降低对Kylin进程所在节点的压力。

③使用FastThreadLocal替代ThreadLocal,可以一定程度上提升Kylin的整体性能。

④通过使用HTTPS,保护了JDBC使用的身份验证信息,使得Kylin更加安全。

⑤默认开启shrunken dictionary,针对高基维进行精确去重的场景,可以显著减少构建用时。

⑥新增一种作业调度器,可以自动发现Job节点,并且可以实现自动故障恢复。

⑦更加及时地清除不必要的数据文件

7、Kylin查询缓存重构

在最新版本中kylin进行了查询缓存重构。以往由于粗粒度缓存过期策略和外部缓存的缺乏,查询缓存在 Kylin 中的使用效率不高。由于激进的缓存过期策略,有用的缓存经常被不必要地清理。因为查询缓存存储在本地服务器中,它们因而不能在服务器之间共享。同时,由于本地缓存的大小限制,并不是所有有用的查询结果都可以被缓存。针对这些不足,开发团队使用签名检查来实现新的查询缓存失效策略,并引入 memcached 作为 Kylin 的分布式缓存,使 Kylin 服务器能够在服务器之间共享缓存。同时添加 memcached 服务器来扩展分布式缓存也是很容易的。其他具体信息查看 。Kyligence博客(Apache kylin 官方博客)链接

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值