如何构建大数据实时多维分析平台

作者/分享人:Chat 实录

本篇文章整理自数果科技联合创始人王劲6月22日在『ITA1024大数据技术精英群』里的分享实录:如何构建大数据实时多维分析平台 。

enter image description here

为什么需要大数据实时多维分析

如何把数据库中存在的数据转变为业务人员需要的信息? 大部分的答案是报表系统。

简单说,报表系统是BI的低端实现。传统的报表系统技术上已经相当成熟,大家熟悉的Excel、水晶报表和Reporting Service等都已经被广泛使用。但是,随着数据的增多,需求的提高,传统报表系统面临的挑战也越来越多,如下:

enter image description here

随着现实和虚拟世界的数据产生速度越来越迅猛,人们开始关注如何从这些数据中获取信息,知识,以及对于决策的支持。这样的任务通常被称作大数据分析(Big Data Analytics)。

大数据分析的难点很多。比如,由于海量数据而带来的分析效率瓶颈,使用户不能及时得到分析结果;由于数据源太多而带来的非结构化问题,使传统的数据分析工具不能直接利用。

大数据实时多维分析技术选型

我们这几年做过很多与大数据实时多维分析相关的技术预研及场景测试,每项技术都有各自的优缺点。

在技术选型过程中, 我们参考了Apache Drill、Presto、Impala、Spark SQL、Apache Kylin等。对于Apache Drill和Presto因生产环境案例较少,考虑到后期遇到问题难以交互讨论,且Apache Drill整体发展不够成熟。

对于Impala和Spark SQL,主要基于内存计算,对机器资源要求较高,单条SQL能够满足秒级动态查询响应,但交互页面通常含有多条SQL查询请求,在超大规模数据规模下,动态计算亦难以满足要求。

对于Kylin,我们从2014年10月刚开源一直在关注并持续做了一些场景的测试,由于Cube的值都是经过预先计算好的,当业务需求发生改变时,Cube需要重新build,从业务人员的角度考虑,带来了不友好的体验。

后来,我们采用了Druid,关注的时间比关注Kylin的时间还要早,我们在2014年6月就研究Druid,当时版本还是0.6,官网文档也不完善,当时搜索Druid还找不到,搜索引擎显示的全是阿里的Druid组件,直到2015年4月,才正式应用内部系统,经过一段时间的线上观察,表现比较好,慢慢基于Druid在多维分析这块推广开来了,团队对Druid的研究及理解也更深入了,到目前为,团队可以驾驭Druid的每行代码了。

Druid的实现原理

Druid的基本概念及原理性的内容,优酷土豆的张海雷在<>中有详细的介绍,在这里就不做详细的介绍了。我这里主要针对它的实现原理简单介绍下。

Druid数据实时处理采用消防的模型,不同的是数据相当于倒灌的方式进入FireHydrant。首先需要定义RealtimeManagerConfig,Realtime模块在启动的时候会加载定义的文件,通过guice依赖注入生成RealtimeManager,然后利用Lifecycle框架,在Realtime模块启动时执行RealtimeManager.start来使整个模型运行起来。

enter image description here

Druid实时写:RealtimeManager主要包括FireDepartment和FireChief,数据源的定义中可以指定partitionNum用于处理较大量的数据,partitionNum决定FireDepartment的个数,每个FireDepartment对应一个FireChief线程,FireChief指挥着FireDepartment的运作,包括initPlumber、plumber.startJob、initFirehose、runFirehose。

具体流程如上图,首先调用FireDepartment.findPlumber,然后调用plumber.startJob初始化线程等待数据接入;initFirehose调用FireDepartment.connect初始化Firehose,然后调用runFirehose从Firehose读取数据到Plumber。

Plumber根据数据的时间和segmentGranularity处理指定的Interval把数据丢给指定的Sink,Sink初始化IncrementalIndex后,利用IncrementalIndex调用addToFacts添加facts, OnheapIncrementalIndex的实现会使用构造好的聚合算子,开始聚合操作,此时写的索引数据为IncrementalIndexSegment,具体索引的格式在<< Druid驱动海量实时多维分析>>分享中有介绍,此处不重述。

需要留意的是如果Sink不能再添加新数据(比如Segment到达最大行数限制)或者与达到持久化时间的间隔(IntermediatePersistPeriod,默认10分钟),将会调用persistHydrant将数据进行持久化,利用锁来切换IncrementalIndexSegment为QueryableIndexSegment,QueryableIndexSegment和IncrementalIndexSegment最大的区别是倒排索引的不一样,IncrementalIndexSegment的索引是简单的Map在数据维度比较多或者基数大的时候性能不高,此时需要控制好IntermediatePersistPeriod来将数据持久化,利用bitmap的方式提高查询性能。

最终调用plumber.finishJob,执行persistAndMerge,合并所有持久化的文件,push到hdfs,等待转交查询给Historical。

此处也可见,FireHydrant有两种数据索引格式,那它是如果做到两种索引的实时查询的?

enter image description here

在Druid中,Segment是可以查询的数据段,支持QueryableIndex和StorageAdapter两种读取索引。对于已经持久化的索引,采用重新加载的方式生成QueryableIndexSegment;对于实时写内存中的索引,利用IncrementalIndexStorageAdapter实现StorageAdapter,从而实现IncrementalIndexSegment,此处只实现了StorageAdapter;然后重新封装为ReferenceCountingSegment。

当一个查询请求由Broker节点分发给实时节点,实时节点利用RealtimeManager实现QuerySegmentWalker,利用Plumber.getQueryRunner来实现查询,最终调用FireHydrant的ReferenceCountingSegment来实现数据的查找。

基于Druid的实时多维分析平台

背景。每天几十亿的增量数据接入,需要满足省份、网络运营商、版本、平台、操作系统、手机型号、网络类型、状态等近40个维度的同时还需要满足秒级的延时和硬件投入成本低的要求。

实现架构。数据存储模型按分钟、小时、天三种时间粒度进行维度设计。分钟、小时时间粒度的维度暂时保持相同,天时间粒度的维度只保留公共维度。分钟时间粒度的数据最长保留2周,天时间粒度的数据最长保留1个月,天时间粒度的数据保留任意长时间。

enter image description here

如上图,红色虚线框起来的数据采集接入部分就不做过多的介绍了,之前的分享中做过详细的介绍,目前大部分公司的采集接入也大同小异,非常类似。

Storm部分,主要应用于数据实时清洗,包括数据业务规则配置,多数据源的join,数据转换等。

Druid部分,包括三部分工作:

一部分,数据的实时写入,通过tranquility-storm组件把数据实时推送给Druild的RealTimeTask,由RealTimeTask小批量存储入到HDFS的分钟库;

二部分, BatchTask,这里特别强调下,也包括两部分内容,一部分通过通过camus离线把数据拉入到HDFS中,再通过BatchTask采用T+1的方式重新跑分钟库数据,确保数据的准确性(为什么要采用BatchTask的方式重新跑分钟库数据,因为所有的实时计算都不能保证数据的100%精准,可能因为网络或其他的原因导致数据延迟到达等原因,所有结合Lambda架构来确保数据的准确性),另一部分通过分钟级的数据降维小时库的数据;

三部分,数据查询部分了,上面的实现原理也介绍Druid的数据查询过程,大家应该大概明白查询是怎么回事了,这里也不做详细的描述。

基于Druid的改进

对Druid做了这么长时间的应用及研究,觉得Druid的实时多维分析有很多天生的特性,从架构原理中就支持Lambda架构。目前我们也主要针对Druild在做一些社区版的开发,如下:

1、RealTimeTask的运维监控的完善
2、支持原始数据的查询
3、支持数据挖掘

微信扫描登录