快手万亿级实时OLAP平台的建设与实践

12月7-8日在北京举办的ArchSummit全球架构师峰会上,快手科技大数据平台架构师李远策分享了快手在OLAP平台的建设与实践。以下为演讲的主要内容,有删节。

快手App目前日活1.5亿,每天会产生数万亿规模的用户行为数据,对这些数据的高效探索是一件很有挑战同时也很有价值的工作。以下重点分享快手建设万亿级数据规模OLAP平台的设计方案以及主要改进过程。

快手OLAP平台概览

image

快手的OLAP平台诞生的时间不长,在2018年4月份之前,一些多维分析的需求还是采用预定义指标加上离线计算的方案,其缺点很明显,首先指标预定义是非常固定的,另外因为采用离线计算,实用性也很差。

在今年4月份上线Druid OLAP分析引擎,加上Superset数据可视化平台,解决了不少业务的痛点。5月,Druid平台升级到了当时社区最新的0.12的版本,在升级过程中解决了时区、文件加载性能等问题。7月,Druid平台每天的录入消息数已经突破1000亿,用户配置的可视化图表也超过1000个。7月份之后平台进入了一个快速发展的阶段,Druid在查询性能和稳定性方面都出现了很多的问题,我们做了非常多的改进。9月,上线了Druid探针系统、时序和维度物化视图功能、Indexing Service细颗粒资源分配等,另外在资源调度层面也做了大量优化工作。截至今年11月,OLAP平台每天摄入消息的数据量峰值已经超过5000亿,用户配置的可视化图表数已经突破1万。

半年来OLAP平台发展速度非常快,得益于基于Druid的高可用架构设计,以及团队伙伴的努力,整个OLAP平台上线至今未出现中型或大型的故障,服务很稳定。

image

快手OLAP平台共有150台物理服务器,接入的数据源超过2000个,每天录入的消息数量在5000亿左右,索引的数据存量约400TB。每天查询次数峰值1000万,这个量是非常大的,但是有很多在程序里触发API的调用,人为触发的比例较小。整体上平均查询时延为50毫秒,P90为100毫秒左右,P99为 500毫秒到1秒。可视化方面,积累的用户看板数有八百多个,图表数超过1万。

快手使用OLAP的业务场景

首先是多媒体质量分析业务。快手使用了全国多家CDN厂商服务,涉及的域名有几百个,每天上报的CDN质量监控数据上百亿。CDN服务质量会直接关系到主站APP用户使用体验,公司CDN质量团队需要实时对CDN监控数据做分析和智能调度,以及对调度效果进行实时的监测。另外,对于CDN质量问题需要做出快速分析和定位,这本身也是一个多维分析的过程,OLAP技术能够很好地满足这个需求。

另外一个业务场景是A/B Test,快手已经上线了约1000个A/B的实验,需要对比的A/B指标多达数千个,每天有数百亿的数据要流入A/B Test平台。对A/B Test指标的分析,也是一个很典型的多维分析的过程,OLAP平台要满足每天几十万次的查询调用需求,查询的时延要保证在百毫秒级。

image

OLAP平台选型时对公司多个业务团队的需求做了调研,总结来讲,大家对以下几个点关注度会比较高。比如超大数据规模的支持,单个数据源可能每天有上百亿的数据量需要录入;查询时延,要保证在毫秒到秒级;数据实时性,很多业务线明确提出实时数据分析的需求;另外还有高并发查询、平台稳定性等,除此之外还有一些相对权重比较低的需求:如数据Schema的灵活变更、精确去重的功能,以及SQU接口的支持等。

image

根据对用户调研的总结,我们对比了现在比较常用的OLAP技术。

  1. 首先,Hive/SparkSQL在数据仓库的领域应用是比较广泛的,但是因为查询时延很难能够满足毫秒到秒级的要求,同时因为是离线计算,数据时效性也比较差。
  2. 其次,ES是一个功能很强大的系统,在中等数据规模场景下能较好地满足需求,但是在万亿和更大的数据规模场景下,数据的写入性能和查询性能都遇到了很大的瓶颈。
  3. Kylin和Druid功能比较类似,考虑到Druid采用OLAP架构,数据时效性相对于Kylin来讲会更好,数据的变更也相对更加灵活,所以最终选用Druid作为OLAP平台的查询引擎。

Druid系统概述

image

上图是Druid系统架构图,其中Coordinator和Overlord是Druid的主节点;Middle Manager主要是负责数据索引,生成索引文件,Historical节点主要负责加载索引文件,同时提供历史数据的查询服务;Broker是查询的接入节点;除此,Druid还需要对元数据进行存储,比如选用MySQL;Middle Manager在产生索引文件的时候,需要把索引文件先发布到一个共享的存储系统里,我们选择了大家普遍采用的HDFS系统。

image

上面提到Druid的查询性能非常好,总结来说主要是因为采用了如下五个技术点:数据的预聚合、列式存储、Bitmap索引、mmap、以及查询结果的中间缓存。下面针对两个点具体展开讲一下。

image

首先讲下数据预聚合。Druid会把一行数据消息分成三个部分,包括时间戳列、维度列以及指标列。所谓预聚合,就是当数据录入到Druid系统时,会按照一定的时间周期把原始数据做一次预先聚合,会根据一个全维度聚合出要计算的指标,也就是要索引的内容。后续所有的查询都是通过这些预聚合的中间结果做二次查询。

image

接下来讲下Bitmap索引。Bitmap索引主要为了加速查询时有条件过滤的场景。Druid在生成索引文件的时候,对每个列的每个取值生成对应的Bitmap集合。如图上所示,Gender为Male对应的Bitmap为“1001”,代表第1行和第4行的Gender为“Male”。举一个查询的例子,假设要筛选Gender =‘Female’and City =‘Taiyuan’的数据,那么只需要把Gender =‘Female’对应的Bitmap “0110”和Taiyuan对应的Bitmap “0101”进行与操作,得到结果为“0100”,代表第二行满足筛选条件。通过Bitmap可以快速定位要读取的数据,加速查询速度。

image

关于Druid模块,Druid支持从kafka实时导入数据,同时也支持批量从HDFS或者HIVE系统进行离线导入;Druid提供了丰富的查询API接口。除了默认提供的Restful接口之外,Python 、Java、Go等编程语言都有第三方的实现API接口。此外,Druid也提供了SQL接口的支持。值得一提的是,Hive在2.2版本之后通过StorageHandler实现了对Druid的支持,这样可以通过Hive SQL查询Druid里的数据,快手内部也在用,但是需要做一些修改工作,比如解决时区问题、Druid数据源维度和指标的大小写敏感问题,以及实现默认的limit、默认时间范围选择等功能。

Druid在快手使用的经验以及一些主要改进点

image

这是快手OLAP的平台架构图,中间部分是Druid自有的组件,数据通过kafka实时摄入和离线从Hive数仓中批量导入。除此之外,我们还配套了完善的Metric系统,探针系统、Druid数据源管理系统等。

image

在万亿甚至几十万亿数据规模场景下,OLAP平台使用过程中也面临了很多挑战。比如如何让查询变得更快,资源的利用率如何更高效,在数据的管理到数据的接入如何更方便,集群平台如何更稳定,针对这些问题我们都针对性的做了改进和优化。

image

首先,稳定性方面我们做了多种的资源隔离部署的方案,在接入层通过代理实现Broker的高可用和负载均衡。

在Historical数据存储层,做了两个层面的数据划分。一是数据的冷热分离,热数据存储在SSD的机器上,当热数据变成冷数据之后会自动地迁移到HDD机器上。因为大部分查询都是查询最近的数据,所以才用SSD的加速效果是非常明显的。考虑到SSD的成本比较高,可以在设置热数据的副本的时候,把其中一个副本放在SSD上,另外一个副本放到HDD的机器上,然后设置SSD副本的权重,大部分的请求还是能够落在SSD机器上。当SSD机器出现故障之后,请求才会发送HDD上,这样能节约不少成本。

除了冷热数据分离的考虑外,因为有些对查询稳定性要求更高,快手通过Tier配置也对特殊业务也做了隔离,特殊的业务数据源索引数据存储在专用的Historical机器上。这样在一些大查询可能会导致historical内存GC或者是系统IO支持Load较高的场景下,其查询性能仍然不受影响。

image

在大规模数据场景下查询性能的加速,我们也做了很多优化。首先是物化视图,会做两个层面的物化视图,一个是维度层面的物化,一个是时序层面的物化。

什么是物化视图,假设一个数据源的原始维度有十个列,通过分析查询请求发现,group1中的三个维度和group2中的三个维度分别经常同时出现,剩余的四个维度可能查询频率很低。更加严重的是,没有被查询的维度列里面有一个是高基维,就是count district值很大的维度,比如说像User id这种。这种情况下会存在很大的查询性能问题,因为高基维度会影响Druid的数据预聚合效果,聚合效果差就会导致索引文件Size变大,进而导致查询时的读IO变大,整体查询性能变差。针对这种case的优化,我们会将group1和group2这种维度分别建一个预聚合索引,然后当收到新的查询请求,系统会先分析请求里要查询维度集合,如果要查询的维度集合是刚才新建的专用的索引维度集合的一个子集,则直接访问刚才新建的索引就可以,不需要去访问原始的聚合索引,查询的性能会有一个比较明显的改善,这就是物化视图的一个设计思路,也是一个典型的用空间换时间的方案。

image

时序物化视图:除了刚才提到的查询场景外,还有一种查询Case,Druid也不能很好满足。比如大跨度时间范围的查询,假设一个数据源的聚合力度是分钟级别,但需要查询最近三个月的数据就比较麻烦,因为需要把过去三个月的所有分钟级别的索引文件全部扫描一遍,然后再做一次聚合的计算。

为了解决这个问题,我们在数据源分钟级别的索引上再新建一个小时级别甚至级别的物化索引,这种情况下聚合效果就会更好,索引整体的size也会比较小。当收到一个新的查询请求时,如果查询要统计的粒度是天级别或者是更高级别的查询粒度,会把查询请求自动路由到天级别物化索引上,这样查询性能也会有一个比较明显的改善。

image

下面讨论下Druid元数据存储系统的性能优化,平台上线以来我们积累了大约几百万的Segment文件,对这些数百万Segment元信息的查询,或者说MySQL Segments表的查询也遇到的性能瓶颈。

首先是Overlord与MySQL之间的交互优化。Overlord在发布新的Segment文件的时候会多次查询Segments表,监控发现会有大量的慢查询。解决方案很简单,针对性地对Segments表增加索引即可。对比优化后的MySQL查询性能,可以从10秒多降到1秒,有10倍以上的提升。

image

另外是Coordinator与MySQL之间的交互性能优化。Coordinator会周期性的去全量扫描Segments表,每次扫描都会花费较长的时间。首先全量扫描完全是没必要的,我们改造成增量扫描的方案,整个扫描的耗时从原来的1.7分钟降到40秒左右。然后更进一步对增量扫描的SQL专门创建了MySQL索引,扫描耗时可以降到30毫秒,整体算下来有上千的性能提升。

image

接下来是Segment文件加载过程的优化,Coordinator扫描segment匹配Rule过程默认是串行实现的,我们对此做了并行化的加速,再加上一些细节点的改进。集群几百万量级的Segment文件协调一遍的耗时从原来的3分钟降低到现在的30秒。Druid元数据系统通过如上几个点的优化后,目前基本上不再有性能瓶颈。

image

快手对Druid集群资源利用率的改进:

首先,每个Kafka indexing task会对应一个Supervisor的服务,Supervisor 的task count是一个固定的值,当用户设置task count比较小时,可能会因为读取Kafka 的lag过大而出现数据延迟,而如果设置的过大会造成资源的浪费。另外,用户在创建一个indexing task的时候,也很难估算task count应该是多少合适。我们的优化方案是让Supervisor根据当前消费Kafka时延的情况,自动调节task count,这样业务高峰期不至于出现数据延时,数据低峰期时也能把资源还给集群,整个集群的利用率有明显提升。

另外是Middle Manager的indexing task资源分配问题。Druid为每个Middler Manager分配一个固定的Slot数,但是因为相对Kafka indexing task来讲Hadoop indexing task其实只是一个Hadoop客户端仅负责提交一个任务,本身并不怎么占资源,这样的话会有一些资源的浪费的问题。针对这个问题的优化思路是,把Middler Manager的task调度配置从按照Slot数改成按照内存大小分配,我们会区别对待不同类型的task,对于Kafka的task和Hadoop的task会默认不同的内存大小,当然用户在提交task的时候,可以指定自己的task内存大小,我们会做一些最大值的限制,防止恶意的提交。

此外,对Segment文件及时的做Compaction会有益于查询性能加速,也能节省存储空间。目前Druid在做Compaction的时候,会提交一个特殊的Compaction task,串行扫描Segment文件进行合并,性能较差。我们对此做了一个并行化的方案,思路是提交一个Hadoop的任务,在Hadoop集群上去并行扫描Segment的信息,然后去做Compaction,性能的提升还是非常明显的。

image

在平台易用性方面我们也做了很多的工作。在平台运营的时候会面临一个问题,每天都有很多数据源要接入,在平台上线初期,管理员是可以参与完成,但是当业务快速增长的时候,这个工作量非常大。数据源接入后,还会面临很多需要修改数据源的维度和指标定义的需求,这些都需要系统化的去解决。

除此之外,很多时候用户对Druid平台或者对自己的数据理解不够深入,也可能对业务的分析需求场景不够明确,在接入数据源时往往会导入大量的维度和指标信息,这就带来一个隐患:维度越多聚合效果就会变差,更甚至会有一些高基维严重影响数据聚合的效果和查询性能。

针对这些问题,我们设计了两套工具,分别是Druid数据源管理系统和Druid探针系统。

image

数据源的管理系统是一个Web管理系统,用户可以在这个系统上完成数据源接入、查看和管理,可以查看的信息包括维度和指标信息、Kafka消费的速率、kafka消费的lag等。上图展示的是数据源管理系统的indexing task列表信息,系统配有权限管理功能,只有数据源的负责人可以修改数据源的维度和指标等配置信息。

image

上图是indexing task详情页面,除了一些基础的信息之外,还可以看到像Kafka消费的速率情况,用户可以自主地去排查自己负责的数据源的线上问题。

image

这张是数据源的新建和编辑页面。用户新建Kafka数据源的过程非常方便, 其中Kafka的信息是从Kafka的管理系统里面直接抽取出来的,用户不需要手动填写,直接点选即可。对于时间戳列和时间戳列的格式,系统会自动抽取用户Kafka的数据做填充,如果是用户写错了时间戳列的格式,也能够自动纠正过来。对于维度和指标系统也预先做了数据的解析提供Suggestion,用户只要用鼠标点选即可。

image

这张图展示的数据源的列表信息,可以在列表上清楚地看到这个数据源的数据量、Segment文件的平均大小、维度和指标信息。此外,如果这个数据源是通过离线任务导入的话,能够会自动关联离线任务的名字,方便快速定位到自己的定时导入任务。

image

Druid探针系统主要解决如下几个问题:

第一,数据源查询热度的分析。探针系统会对Druid所有的数据源做总体的查询热度排名,这样管理员可以知道哪些数据源是查询的大客户,会做针对性的“关照”。此外,还可以发现一些没有查询请求的冷数据源或者僵尸数据源,并通知用户去做下线处理,避免占用集群的资源。

对於单个数据源,探针系统还可以对这个数据源内部的维度和指标做查询热度的分析,了解哪些维度是经常被查询的,哪些维度和指标是不常查询的冷维度或指标,特别是还能发现一些既是冷维度又是高基维的维度,这种Case会严重影响查询性能,要及时通知用户进行优化。

image

下面讲一下OLAP平台数据可视化方面的工作。一个强大的可视化工具,是OLAP平台必备的组件,我们采用了开源的Superset方案。Superset是Airbnb开源的、能与Druid深度集成的、交互式的、高效的、数据分析和可视化平台,它的功能非常强大,支持种类丰富的数据可视化的图表。

image

截至目前,我们的Superset已经积累了上万个图表,用户在使用Superset过程中也遇到很多问题,针对这些问题我们对Superset同样做了大量的改造。包括数据的同步、权限管理、报警功能、产品设计的一些交互改进等。

image

针对几个重点的改进点做下介绍,比如对多time shift的支持,所谓time shift就是可以在一张图里面同时绘制出来当前值与前一天同比和环比的指标对比。这里展示的是当前这一天与前一天,以及上周同天指标对比情况,用户可以加任意多的其他日期的指标对比到同一张图里面。除了这种时序线图之外,我们对其他图表也做了大量的time shift支持。

image

这里展示的是Superset同一个看板里面多个图表,在鼠标滑动窗口进行滑行的时候能够联动刷新的功能,对其中一个图表进行时间范围选择,其他图表能够关联进行刷新,这在进行多表关联分析的时候还是比较实用的。

image

这里展示的是Superset报警功能的设计。公司很多监控数据都是依赖Druid和Superset做数据分析,对报警需求也是非常强烈。我们参考了Grafana的报警功能的设计,在Superset上也实现了类似的功能,用户可以在平台上自定义一些报警维度、指标、检查周期、报警级别等。

image

总结:快手对Druid的改进

在性能提升方面,我们做了时序和维度两个层面的物化视图以及元数据方面的交互优化。在资源管理层面,实现了Supervisor indexing task的自动伸缩、Middler Manager细粒度资源分配以及并行Compaction。在稳定性层面,设计了Broker和Historical的隔离部署。在平台易用性层面,自研了数据源的管理系统、数据探针系统,以及引入Superset数据可视化平台。

最后分享未来快手OLAP平台的一些工作计划。首先,我们会引入一些新型的OLAP的技术,比如Clickhouse。第二,我们在考虑OLAP与Adhoc,以及例行报表的整合,希望OLAP技术能够在离线数据分析方面也有更大的发挥空间。第三,从数据的流入到数据的可视化提供一站式的服务,降低技术人员和非技术人员的使用门槛。第四,希望平台能够从技术输出向产品化、服务化的方向去演进。

嘉宾介绍:

李远策:快手科技大数据平台架构师

快手大数据平台架构师,数据查询引擎团队负责人。负责公司 SQL 引擎、OLAP 引擎、多维可视化平台的研发以及在公司的应用。曾供职于奇虎360,是开源项目 XLearning 的作者。主要研究领域包括分布式计算、OLAP 引擎、SQL on Hadoop、AI on Hadoop 等。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章