【.com原稿】随着公司业务的快速增长,数据量越来越大,数据的种类也越来越丰富。分析师对数据处理的响应延迟要求也越来越高。传统的大数据处理工具已经不能满足业务需求。尤其是在OLAP分析场景中,需要对各种维度、度量进行rollup、drilldown、slice、dicing分析,并要求实时返回分析结果。因此,我们调研比较了目前主流的一些OLAP分析工具,引入了聚合计算实时分析的开源分析工具Druid。Druid简介说到Druid,首先想到的是阿里的Druid数据库连接池,而本文介绍的Druid是大数据场景下的解决方案,是一个需要在复杂环境下进行交互式实时数据展示的BI海量数据。/OLAP工具。它具有三个特点:处理的数据量比较大。可以进行数据的实时查询和展示。它的查询方式是交互式的,这也说明它的查询并发是有限的。目前,Druid广泛应用于阿里、滴滴、知乎、360、eBay、Hulu等国内外各个公司,Druid之所以能够在OLAP家族中占据一席之地,主要还是在于其强大的功能MPP架构设计。关于它的架构,这里就不赘述了。感兴趣的同学可以登录官网druid.io了解更多。除了MPP架构之外,它还使用了四项重要的技术,即:预聚合列存储字典编码位图索引预聚合是Druid非常大的亮点,通过预聚合可以减少数据存储,避免查询很多不必要的计算。由于大多数OLAP分析场景只关心某列或某几列的索引计算,数据非常适合列式存储。在列式存储的基础上,加上字段编码,可以有效提高数据的压缩率,然后位图索引可以让很多查询在计算机层面直接转化为位计算,提高查询效率。既然Druid是一个OLAP工具,那么它和其他OLAP工具有什么区别呢?图1:OLAP工具对比从上图可以看出,Kylin和Druid相比其他两者整体还是有优势的:与Kylin相比,Druid不具备管理模型和Cube的能力,而Kylin则不能提供实时查询。与ES相比,Druid的优势在于聚合计算,ES的优势在于检查细节。在苏宁,Druid的使用一般用于需要对数据进行实时聚合查询的场景。Druid在苏宁的应用场景苏宁在很多业务场景中都使用了Druid。本文将列举两个例子,分别是商店App系统和诸葛系统。门店APP系统门店APP系统是集数据服务、销售计费、会员营销、收发订单、绩效管理、V购用户沟通、学习中心于一体的门店店员移动办公平台。其销售界面如下:图2:销售界面图3:客流界面店铺App业务概况如下:数据量:保存近年数据。数据接入方式:Kafka实时数据接入,第二天的离线数据覆盖昨天的数据。查询方式:实时查询。业务实现:topN实现销售曲线展示,groupby组楼层客流分布,timeserise做天汇总。诸葛报表系统诸葛报表系统是苏宁的重要系统之一。可以帮助商家进行决策分析,减少人工分析成本,帮助提升销售。系统可以主动向商家发送销售数据,促进销售关注和分析。图4:诸葛报表系统诸葛业务概况如下:数据量:保存近年数据。数据接入方式:Kafka实时数据接入。查询方式:实时查询。业务实现:topN实现销量饼图展示,groupby实现区域销量排名。以上简单介绍了什么是Druid以及Druid在苏宁两个业务场景的应用。苏宁德鲁伊的平台建设是怎样的?图5:苏宁Druid两种架构的平台搭建主要有两种:通过OCEP(提供负载均衡、查询路由功能等),利用Druid原生能力满足一系列业务需求。结合苏宁天工系统和百川系统,Druid作为OLAP引擎的底层加速系统,提供统一的报表查询能力。目前大部分业务采用第一种方式使用Druid,少数业务采用第二种方式。随着第二种方式的成熟,大家的业务也会逐渐从第一种方式迁移过来。转到第二个,实现资源的统一。基于OCEP的平台架构图6:基于OCEP的平台架构平台主要依托OCEP对外提供一系列OLAP查询服务,满足集团内各业务的维度指标分析需求:通过Tranquility实时消费业务数据并将其发送给Druid将realtimepeonhandoff持久化到HDFS,coordinator将其加载到historical中提供查询服务。通过苏宁自研的IDE任务调度系统,将HDFS上的离线数据(一般为数仓数据)通过mapreduce任务处理后写入Druid指定的HDFS路径,同时也由coordinator加载到historical,提供查询服务。最后通过OCEP将业务查询路由到各个broker,由broker分发到historical,经过historical计算,逐层返回给业务。基于OLAP引擎的平台架构图7:基于OLAP引擎的平台架构为了保证数据的一致性和统一性,平台基于OLAP引擎,为集团各业务提供统一的维度指标分析系统:百川系统通过OLAP引擎构建模型,OLAP引擎根据业务需求将模型拆分成若干个Cube,存储在底层的Druid、Hive、PG、ES中。我们称此过程为模型加速。此外,百川系统本身也会构建各种指标。业务方如天工、诸葛等系统选择百川提供的一个或多个指标构建报表,其查询请求将发送至百川系统。百川系统构造SQL语句,然后将请求发送给OLAP引擎。OLAP引擎通过底层Spark平台解析SQL语句,将请求路由到Druid、ES、Hive和PG。其中,时序数据的聚合查询会路由到Druid平台上,最终的查询结果逐层聚合到上层业务系统。整个系统的监控通过云集系统、华佗系统等进行,系统日志接入云集,系统的指标信息接入华佗。随着Druid平台建设的不断推进,越来越多的业务使用Druid,在使用过程中也会遇到各种各样的问题。下面总结了苏宁业务开发者在使用Druid过程中遇到的一些问题希望对正在阅读本文的读者有所帮助。使用Druid的建议本节主要是想结合实际问题给大家提供一些使用Druid的建议,供大家参考。①什么样的业务适合德鲁伊?建议如下:时序数据:Druid可以理解为时序数据库,所有数据都必须有时间字段。实时数据接入可容忍数据丢失(tranquility):Tranquility目前存在数据丢失风险,建议实时和离线结合使用,实时接收当天的数据,覆盖今天的所有数据第二天都离线,保证数据的完整性。OLAP查询而不是OLTP查询:Druid查询并发有限,不适合OLTP查询。去重计算不准确:目前Druid的去重计算不准确。无Join操作:Druid适合处理星型数据,不支持关联操作。数据没有update更新操作,只覆盖段粒度:由于时序数据的特性,Druid不支持数据更新。②如何设置合理的Granularity?图8:粒度设置首先解释一下segmentGranularity和queryGranularity,前者是Segment的组成粒度,后者是Segment的聚合粒度。要求queryGranularity小于等于segmentGranularity,然后在导入数据时按如下规则设置。segmentGranularity(离线数据导入的设置):导入的数据在天级别内:“小时”或“天”。导入的数据在日级别之上:“day”。导入的数据在年份级别以上:“月”。需要注意的是,这里我们只是简单的通过interval来设置segmentGranularity。更合理的做法应该是综合衡量每个段的大小和查询的复杂度。考虑到安宁实时任务的特殊性和数据的安全性,我们建议在导入实时数据时将segmentGranularity设置为“hour”。queryGranularity:根据业务查询的最小粒度和查询复杂度确定。假设查询只需要小时粒度,则此参数设置为“小时”。③是否需要在维度列中定义需要去重的维度?图9:去重维度定义如果去重维度只需要去重计算,没有其他功能,比如过滤或者作为分组字段,我们建议不要将其添加到维度列中,因为如果不添加它,数据的预聚合效果更好。④如何选择查询方式?三个常用查询:selectsum(A)fromDSwheretime>?[timeseries]从DS中选择sum(A)wheretime>?groupbyBorderbyClimit2[topN]selectsum(A)fromDSwheretime>?groupbyB,CorderbyClimit2[groupby]timeseries用于没有维度分组的场景,topN用于单维分组查询场景,groupby用于多维分组查询场景。由于groupby没有下推限制(新版Druid做了优化,虽然可以下推,但是指标排序不准确),所以对于单维分组查询,尽量使用topN查询。我们所做的工作从德鲁伊引入苏宁后,很快就担负起了OLAP分析的重任,作为支撑模型和指标的底层核心引擎,为集团各业务线提供OLAP分析服务。过去,我们做了很多工作,本文列出其中一些以供说明。①OCEP(Druidclusterfrontproxy)图10:OCEP(Druidclusterfrontproxy)OCEP是一个Druidclusterfrontproxy,通过它提供更完善的Druid集群和服务能力,解决目前Druid服务存在的各种问题。它提供的主要功能有:访问认证(为每个数据源提供token访问认证,保证数据安全)。访问审计(每次查询都会生成唯一的queryId,提供完整的请求来源)。请求拦截(针对意外访问,制定拦截策略,细化到具体数据源和查询语句)。请求路由(根据集群名称和数据源将请求路由到指定的Druid集群,并根据后端broker的压力均衡各个broker上的请求负载)。服务隔离(可以设置策略,将来自不同数据源的请求路由到指定的broker,实现broker隔离)。②Druid查询客户端官方提供的查询方式是写一个Json文件通过HTTP请求Druid。但是,这种方法的缺点也很明显。第一,Json内容写起来麻烦,而且格式容易写错。另外在用Java开发的时候,有一个不利于定位的问题。图11:Json语句所以我们封装了一层JavaAPI,如下图所示:图12:DruidJavaClient③资源隔离图13:资源隔离不同业务的数据量不同,对服务稳定性的要求也不同。我们通过以下三点实现业务层面的隔离:历史分组:集群设置不同的层来存储不同的业务数据。Broker隔离:通过OCEP设置数据源白名单,不同的broker只提供一个或多个数据源查询。冷热数据隔离:通过设置数据源的规则,将冷热数据分别存储在不同的层级中。德鲁伊白名单控制。集群的稳定性对于防止不受控制的机器对集群的无效查询和攻击至关重要。我们在一个模块中添加一个白名单扩展来控制服务器端的白名单。并且可以针对不同的服务进行控制,白名单配置文件写在Druid元数据的config表中,实现动态更新。图14:白名单扩展图15:Druid白名单配置④Druid在离线导入期间控制间隔。部分离线导入任务占用YARN资源过多。单个任务会消耗数千或数万个容器资源。分析发现业务设置的segmentGranularity不合理,最终会导致segment过多,HDFS小文件较多。所以我们在霸王服务器上添加参数“druid.indexer.intervals.maxLimit”来判断离线任务。如果segmentGranularity和interval设置不合理,将禁止提交。例如segmentGranularity设置为小时,间隔设置为interval为1年。这是不合理的,服务器会禁止数据导入。图16:intervals的离线导入控制参数配置⑤Coordinator自动合并Segment时,启动的并发任务数在集群中进行控制。我们启用了协调器自动合并段的功能。协调器默认每30分钟,启动合并线程,并扫描所有数据源,根据需要合并太小的段。每当一批段满足合并要求时,就会请求霸主启动合并任务。如果集群中有很多smallsegment,就会启动无数的merge任务,阻塞middleManager的peon资源。我们增加参数来限制并发合并任务的数量,以保证每个合并线程只启动一定数量的任务。图17:设置合并任务的并发数⑥Druid监控对于任何系统来说都是非常重要的,可以帮助我们提前预知系统的健康状态。Druid监控主要有两个点,业务查询状态和平台运行状态。前者主要包括数据源查询量、查询耗时、网络流量等;后者主要包括各个服务的gc状态、cpu和内存使用情况,以及空闲的Jetty线程数。我们的监控方案是Druid_Common集群和Druid_OLAP集群互相监控,存储彼此的metric信息,然后通过superset展示。图18:Druid监控方案的未来规划Druid在苏宁还有很长的路要走。在查询优化和集群管理方面有很多事情要做。查询优化:高基数问题:高基数查询一直是OLAP查询的一大痛点。新版本虽然支持limitpushdown,但是只有维度排序才能保证精度。SQL支持:升级Druid版本,提供丰富的SQL查询接口。精准去重:目前Druid的去重计算,无论是HyperLogLog、ThetaSketch还是最新版的HLLSketch,都是不准确的。后面会考虑能不能通过整合bitmap来解决。集群管理方面:Kafkaindex服务使用:Tranquility时间窗限制会造成数据丢失,延时较大,实时peon管理不够灵活,在某些场景下也可能造成数据丢失。Kafka索引服务实时调用Kafka底层API,管理更加灵活,依赖Kafka实现数据不丢失、不重复制。数据源跨集群迁移:Druid非常依赖Zookeeper进行数据导入和数据查询。当集群规模变大,数据源数量增加时,Zookeeper可能成为瓶颈。这种情况下需要进行数据源迁移,迁移工作涉及数据源元数据和HDFS数据的迁移。如何让迁移工作轻量化,是我们需要思考的问题。作者:李成录简介:苏宁易购IT总部大数据中心大数据平台研发工程师。多年大数据底层平台开发经验。目前负责苏宁大数据底层平台计算资源调度平台和Druid平台的研发,为离线计算平台和实时计算平台提供资源调度解决方案,提供基于Druid的OLAP平台,提供为集团各项维度指标分析业务提供稳定保障。【原创稿件,合作网站转载请注明原作者和出处为.com】
