美文网首页多维分析大数据开发
[魅族]大数据多维分析引擎在MEIZU的实践

[魅族]大数据多维分析引擎在MEIZU的实践

作者: 葡萄喃喃呓语 | 来源:发表于2017-02-08 08:54 被阅读150次

//
【微学堂】大数据多维分析引擎在MEIZU的实践
http://mp.weixin.qq.com/s?src=3&timestamp=1486433778&ver=1&signature=na0ytajPH-136OH6OuYhCpd5mKGJzLdNOWunnkPssO1KQxFA69YhoGqkMO9K7tLYhFR8Pb5x2XrgAYsUjWimIThmrrSMHXd9GEH21xUrK91yydHRp52nQWhrqANCOECY3vYnV60MTgJpWDfL4imhlljOo--rqq2IYpujGwEhs=

我是来自魅族科技的赵天烁,今晚跟大家分享apache kylin在魅族的一些实践。
闲话不多说我就直接进入正题了~

相信群里的各位同学应该都是对数据库技术感兴趣的,apache kylin作为大数据分析引擎这一块近年来崛起的新星已经受到越来越多人的关注。我今天的内容主要分为以下几个方面:
Kylin的基本 **介绍 **
Kylin核心概念和特性
** Kylin **在魅族的应用案例(场景+优化实践)

在大数据的时代,越来越多的企业开始使用Hadoop管理数据,但是现有的业务分析工具(如Tableau,Microstrategy等)往往存在很大的局限,如难以水平扩展、无法处理超大规模数据、缺少对Hadoop的支持;Kylin就是为了解决这些问题而设计的。Apache Kylin,中文名麒(shen)麟(shou) 是Hadoop动物园的重要成员。Apache Kylin是一个开源的分布式分析引擎,最初由eBay的几位华人工程师开发贡献至开源社区,这也是它取名麒麟的一个重要原因,kylin是为数不多的由华人贡献至apache社区并能够成为顶级项目的。它提供Hadoop之上的SQL查询接口及多维分析(OLAP)能力以支持大规模数据,能够处理TB乃至PB级别的分析任务,能够在亚秒级查询巨大的Hive表,并支持高并发。
[图片上传中。。。(1)]
Apache Kylin于2014年10月在github开源,并很快在2014年11月加入Apache孵化器,于2015年11月正式毕业成为Apache顶级项目,也成为首个完全由中国团队设计开发的Apache顶级项目。于2016年3月,Apache Kylin核心开发成员创建了Kyligence公司,力求更好地推动项目和社区的快速发展。

Apache Kylin于2014年10月在github开源,并很快在2014年11月加入Apache孵化器,于2015年11月正式毕业成为Apache顶级项目,也成为首个完全由中国团队设计开发的Apache顶级项目。于2016年3月,Apache Kylin核心开发成员创建了Kyligence公司,力求更好地推动项目和社区的快速发展。

Kyligence是一家专注于大数据分析领域创新的数据科技公司,提供基于Apache Kylin的企业级智能分析平台及产品,以及可靠、专业、源码级的商业化支持;并推出Apache Kylin开发者培训,颁发全球唯一的Apache Kylin开发者认证证书。

这里插一句题外话,在做分析引擎选型的时候,除了项目本身的成熟度之外,社区的活跃度和是否有一家商业公司在背后推动一直是我的一个重要的选择标准,商业化公司在开源技术的组织,标准化,推广等各个方面都能够弥补社区的不足之处

刚才对kylin做了一些基本的背景介绍,接下来,我们来逐步深入的探究一下kylin究竟是如何能够做到在PB级的数据量下提供亚秒级的查询响应的

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

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

下面我们聊一聊kylin的一些基本原理

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

算法优点
此算法充分利用了MapReduce的能力,处理了中间复杂的排序和洗牌工作,故而算法代码清晰简单,易于维护;

受益于Hadoop的日趋成熟,此算法对集群要求低,运行稳定;在内部维护Kylin的过程中,很少遇到在这几步出错的情况;即便是在Hadoop集群比较繁忙的时候,任务也能完成。

算法缺点
当Cube有比较多维度的时候,所需要的MapReduce任务也相应增加;由于Hadoop的任务调度需要耗费额外资源,特别是集群较庞大的时候,反复递交任务造成的额外开销会相当可观;

由于Mapper不做预聚合,此算法会对Hadoop MapReduce输出较多数据; 虽然已经使用了Combiner来减少从Mapper端到Reducer端的数据传输,所有数据依然需要通过Hadoop MapReduce来排序和组合才能被聚合,无形之中增加了集群的压力;

对HDFS的读写操作较多:由于每一层计算的输出会用做下一层计算的输入,这些Key-Value需要写到HDFS上;当所有计算都完成后,Kylin还需要额外的一轮任务将这些文件转成HBase的HFile格式,以导入到HBase中去;这些频繁的对HDFS的读写操作都是使得Cube构建的整体时间变长的重要原因

总体而言,该算法虽然简单清晰易于维护,但是效率较低,尤其是当Cube维度数较大的时候。
[图片上传中。。。(2)]
Fast Cubing是1.5之后的版本新增的一种cube构建方式,最大化利用Mapper端的CPU和内存,对分配的数据块,将需要的组合全都做计算后再输出给Reducer; 由Reducer再做一次合并(merge),从而计算出完整数据的所有组合。如此,经过一轮Map-Reduce就完成了以前需要N轮的Cube计算
[图片上传中。。。(3)]
这种算法还有另外一个优点,如上图所示:第一步会计算Base Cuboid(所有维度都有的组合),再基于它计算减少一个维度的组合。

基于parent节点计算child节点,可以重用之前的计算结果;当计算child节点时,需要parent节点的值尽可能留在内存中; 如果child节点还有child,那么递归向下,所以它是一个深度优先遍历。当有一个节点没有child,或者它的所有child都已经计算完,这时候它就可以被输出,占用的内存就可以释放。

如果内存够的话,可以多线程并行向下聚合。如此可以最大限度地把计算发生在Mapper这一端,一方面减少shuffle的数据量,另一方面减少Reducer端的计算量。

接下来我们看一下kylin是如何存储这些cube的数据的

[图片上传中。。。(4)]
MapReduce的计算结果最终保存到HBase中,HBase中每行记录的Rowkey由dimension组成,measure会保存在column family中。为了减小存储代价,这里会对dimension和measure进行编码。查询阶段,利用HBase列存储的特性就可以保证Kylin有良好的快速响应和高并发。

有了这些预计算的结果,当收到用户的SQL请求,Kylin会将SQL转换成查询计划(Apache calcite),把本该进行的Join、Sum、Count Distinct等操作改写成HBase的get和scan的查询操作。
[图片上传中。。。(5)]
相比于很多其他开源分析引擎只开放出来一个基于console的简单交互入口的内核相比,kylin把一个集成了简单web-IDE,cube创建编辑,building过程监控和管理、系统配置、权限管理的一个相对完善的管理界面都打包在了kylin的开源发布包中,这使得上手使用kylin会变得非常简单。
[图片上传中。。。(6)]
Kylin提供了一套基于完整的REST API,并且支持符合ANSI SQL标准的语法以及JDBC、ODBC的驱动,这样我们可以非常方便的将现有的应用切换到kylin上面来,如果有需要的,可以使用kylin的REST API把cube的构建过程集成到我们自己的内部平台当中去,这些紧靠行业标准的选择也是kylin能够快速蹿红的一个重要原因
不那么新的新特性---Parallel Scan

[图片上传中。。。(7)]
1.5之后的一个版本中,kylin对HBase存储结构进行了调整,将大的Cuboid分片存储,将线性扫描改良为并行扫描。基于上万查询进行了测试对比结果显示,分片的存储结构能够极大提速原本较慢的查询5-10倍,但对原本较快的查询提速不明显,综合起来平均提速为2倍左右
实验中的feature终于转正---Streaming Cubing

[图片上传中。。。(8)]
Kylin从1.5早期的版本中就开始实验一种Streaming Cubing的方式,当时的实现方式无愧于实验feature的称号,我们也简单测试过,日常运维各种问题,mini-batch进程crash、数据丢失、一但crash基本上就得重头来过,数据不可能恢复,所以那时的streaming cubing还不是一个线上可用的状态。

虽然看起来可以提高cube的构建效率,大幅度提升数据的实时性,但是由于设计的不合理那时候还不能在生产中使用

最近在1.6中终于有一个看上去很美的streaming cubing实现了。新版用一个MR任务去跑每一个kafka分区,把kafka中的数据写入HDFS,之后就可以和从hive中build一样使用通用kylin cube building过程了
[图片上传中。。。(9)]

这样做有以下几个好处
允许多个segment(一个segment就是hbase中存储cube数据的一个片段)并发build

允许segment之间出现时间窗口重叠(很重要)

其他不那么新的新特性
支持精确的distinct计数(所有数据类型)---1.5.3

支持针对不同的Project设置不同的MR job运行队列---1.5.3

Top N指标支持多列group by ---1.5.3

主动监测OOM,将堆栈中的cuboid缓存到本地磁盘---1.5

查询明细数据(RAW MEASURE)---1.5.2

支持Hive视图作为lookup 表---1.5.2

综上,如果大家想要在生产环境中使用kylin的话,推荐大家尝试1.5以上的版本。

Why Kylin?

刚才聊的都是kylin的功能特性和设计,接下来看看我们为什么要选择kylin,或者说kylin适合什么样的场景?

1、平台体系完善,成熟度高,部署简单,易用

2、在高并发访问下保持不错的性能,随着数据量和维度组合的增长,性能衰减也不会特别明显

3、Cube模型的合理设计,可以减少人工配置 ETLjob的数量

4、可以在数据准确度、存储空间、性能之间灵活调整,找到最适合需求场景的平衡点

5、标准SQL语法+JDBC/ODBC驱动可以很方便的和现有系统做集成

7、社区活跃,有Kyligence这样的商业公司在背后推动

8、支持准实时的数据更新,未来有准实时OLAP需求也可以复用kylin

9、底层基于已经相对成熟的Hive、HBase,整体技术栈并不复杂,日常运维成本低

hobo文库本下面是Kylin的架构图应用场景特征

我们总结了一下日常接入kylin的需求需要满足的基本特征,这些描述都是基于我们自身的技术体系和需求的特点而决定的,仅供大家参考,并不是一定要这样

I. 数据量大,同时对查询性能有需求

数据量不大直接用mysql好了,对查询性能没有要求的可以用其他的诸如impala或者spark都可以

II. 数据实时性要求不高(目前最高到小时级更新)

只针对于非实时的cubing,Streaming cubing目前还在研究中,方案成熟后可以很大程度上提高实时性

III. 维度组合和查询条件组合在可预见的范围内


由于Cube模型需要预先构建,因此维度的组合和条件必须是可预见的,如果用户传入的维度building时没有包含,自然是查询报错了。对于查询自由度过高的场景还是推荐用hive、spark或者impala

IV. 数据总量大,但条件扫描范围不会太大的。

不适合需要大范围模糊搜索排序的场景(类似search),这类场景自然是ES这类搜索引擎的强项,kylin并不擅长。
[图片上传中。。。(10)]
上图中的性能指标都是优化后的,前期刚上线的时候也是经历了多伦的痛苦优化。

先看看上面那个例子优化前的状态

优化前:

Cube原始记录 6亿---一个月数据
build后的Cube Size 1.9T
单次查询扫描一周数据,HBase频繁超时,Region Server经常被拖死,平均响应时间近30s

维度基本上全选,mandory、维度继承从来不用,结果如上。。Cube存储空间相比原始数据膨胀了700倍,Hbase region server一天挂N次,运维小哥苦不堪言。

优化后:
活用Aggregation Groups

http://kylin.apache.org/blog/2016/02/18/new-aggregation-group/

将使用场景进行分组,对应不同的group

大基数维度创建单独的group,尽量确认需求,收缩条件组合范围,include中只包含相关的维度

低基数的维度可以单独建立一个group,加上必选条件维度,把低基数的维度都设置成Mandatory,这样维度组合出现时kylin会灵活进行内存内二次聚合,但因为这些维度基数都不大,对性能不会影响太多

二选一或多选一的条件维度不要包含在统一个group(比如崩溃时间和上传时间)

同时有好几个大基数group的话可以考虑每个group单独建一个cube(避免cube膨胀,row key结构也更合理)

kylin.query.mem.budget

Rowkey

有日期分区字段的,可以将日期转成只包含变化范围的数字:
比如原始格式是字符串的2016-07-15 12:31:25,只保留一个月的数据,同时查询是按天维度group by 不关心小时分钟可以把日期转成yyMMdd ,160715,这样可以极大的降低维度基数

基数小的维度在前面

低基数的维度尽量用dict编码(100w以内)

合理使用层级维度/派生维度
http://kylin.apache.org/docs15/howto/howto_optimize_cubes.html

Kev1nZ:优化后效果


Cube build后大小降低到500G上下
50%的查询性能在2s以内
Cube build时间缩短30%

本来希望整理一些streaming cubing的实践和优化相关的内容,但是由于社区里的很多实践最近变化比较大,还不太稳定,以后等稳定过之后再有机会可以一并交流。

好了,我今天分享的内容就到这里,谢谢大家!

相关文章

网友评论

    本文标题:[魅族]大数据多维分析引擎在MEIZU的实践

    本文链接:https://www.haomeiwen.com/subject/wekvittx.html