编者按:本文是由网易游戏的大数据工程师撰写的基于Presto+Alluxio的adhoc查询方案在网易游戏的实践分享(作者详情见文末)
业务背景
作为全球领先的游戏开发与发行公司,网易游戏不仅自主研发了《梦幻西游2》《大话西游2》《天下3》《乱斗西游》《梦幻西游手游》等几十款倍受玩家喜爱的热门端游和手游,更独家代理了《魔兽世界》《炉石传说》等多款风靡全球的游戏。网易游戏强劲的需求驱动其内部数据平台来构建处理海量数据的业务能力。例如,网易游戏每天就有30TB左右的原始数据新产生出来;而原始数据在经过ETL逻辑处理后, 会进一步产生30TB数倍大小的ODS中间表数据。
数据分析人员通常会经两种途径来访问这些海量的原始或表格数据:
- 常规的业务指标会经由成熟的报表系统落到到数仓存储系统;
- 除此外还存在着另外一种类型的adhoc(即席)报表查询需求,其业务特点为:
查询条件灵活,无法事先确定查询的表名和SQL语法
查询的数据量相比于离线ETL一般比较少
能够提供查询过程的进度百分比(经过与业务同学的沟通,发现对这个的需求出奇的高)
查询实效性要求高,以满足业务人员数据探索的需求。根据数据量的不同,查询平均时延要求在2-15s左右
目前业界比较常见的adhoc查询方案是SQL on Hadoop。根据这个思路以及内部的组件积累方向,目前在网易游戏平台内部存在大量的基于Hive on MR/Hive on Tez/Spark SQL的查询场景。然而这些方案都存在着一定的问题:
- Hive on MR方案一般适用于ETL逻辑和离线数据查询场景,其查询速度比较慢。根据业务SQL的复杂度不同,其查询性能一般在分钟到小时级别,达不到adhoc查询性能的要求(平均2-15秒)
- 基于DAG的Hive on Tez方案优化了查询引擎,相对于Hiveon MR方案,在部分查询场景下速度能达到秒级别返回,但是性能提升不明显(从后续的测试结果来看,速度一般在30秒以上)
- 基于内存计算和DAG的Spark SQL的并发查询方案能够一定程度地提升查询速度(从后面的性能测试结果来看,查询时间在10到30秒左右)。但是存在着以下缺点:
1、SparkSQL在进行查询的时候,一般都需要先向YARN申请一定量的资源,在集群比较繁忙的时候,申请资源的时间往往都是秒到分钟级别,会极大程度影响查询速度;
2、Spark SQL存在大量的HDFS IO: 源数据在HDFS上;另外,Spark SQL的默认的shuffle配置会导致超过executor内存大小的中间数据落到HDFS IO。但是从我们线上环境来看,datanode的磁盘IO延迟和吞吐极不稳定—特别是在离线作业高峰期的时候更加明显—导致查询的性能存在比较严重的波动。
在去年(2017年)8月份,业务方给我们提了一个adhoc查询的需求,其大致背景为:为游戏策略提供一个玩家级粒度的多维查询数据实时分析平台(一个查询的WEB前端平台),以分析玩家行为及辅助业务决策。旧的解决方案基于HBase storage+coprocesser,存在一些限制:由于存在多维护查询导致大量的HBase全表扫描,耗时长(分钟级别);需要把Hive表经过一定的数据转换后存到HBase,流程繁琐。
在与业务方沟通过后,总结了业务方对后续新方案的需求如下:
1、优良且稳定的查询性能:该方案的性能需要明显好于旧的解决方案,且查询性能相对波动较小。业务方给的预期查询平均时间为10秒左右
2、降低数据转换成本:希望能直接基于Hive表进行查询,减少数据转到其他存储的成本
3、能够能有一个能查看adhoc查询进度百分比的接口:在查询时间比较长的情况下,有个进度显示能够很大程度上提高用户体验
基于以上背景,我们尝试选择了基于Presto+Alluxio的联合查询方案:
Presto(http://prestodb.io)是一个开源的基于MPP架构的分布式SQL查询引擎,解决大规模商业数据仓库的交互式分析和处理速度的问题。
Alluxio(www.alluxio.org)是内存级别的存储解决方案,是连接计算资源和存储资源的中间件。其通过将数据缓存在自身管理的MEM,SSD,HDD等存储介质的方法,实现数据读取加速和远程数据本地化的作业。这种实现特性对于计算存储分离场景下的性能加速起到了关键性的作用。
基于Presto+Alluxio的联合查询方案能够比较完美解决业务提出的需求:
- 基于MPP架构的查询引擎Presto性能优秀,是目前adhoc查询优秀的解决方案。除了初始时源数据需要从HDFS读取以外,后续所有执行过程的数据都在的内存中;
- 为了解决源数据从HDFS读取可能出现的性能波动,把业务常用的数据load到Alluxio的内存缓存中,实现全流程数据内存化;
- Presto可以直接查询Hive中的数据,不需要进行额外的数据转换,也提供了查询过程进度百分比的接口,方便嵌入到业务前端;
- 通过Alluxio在Presto计算集群上管理缓存存储并对接HDFS,让这种资源隔离的卫星集群的架构简单和易维护,而无需额外的ETL步骤。
方案架构
我们搭建的Presto+Alluxio框架示意图如下所示:
关于这一架构更多的部署和配属细节说明如下:
- 为保证查询性能的高效和稳定,Presto+Alluxio服务部署在一个独立的卫星集群之上,与保存和服务全量数据的HDFS的datanode集群是分开部署的。这样从架构上保证查询框架独享隔离的计算资源。而在这一卫星集群里Presto和Alluxio是混合部署:把Presto的coordinator和Alluxio的master部署于相同的节点上,同理也把Presto和Alluxio的worker部署于相同的节点上。目前最大的集群有100个节点。
- 介于内存资源的稀缺性,Alluxio的存储并没有完全使用内存作为存储,而是使用了分级存储的策略,由内存层(MEM)和硬盘层(HDD)两级组成。我们为每个Alluxio worker配置了10GB的内存和800G的HDD存储,通过Alluxio自带的缓存eviction策略进行缓存清理。
- 考虑到Hive metastore在离线作业高峰期存在性能波动(在我们的环境中,
get_table
api 99th时延在高峰期的性能是低峰期的10倍以上),我们为Presto的adhoc查询服部署了一个独立的Hive metastore实例。 - 由于全量数据保存在HDFS当中,在Alluxio当中缓存的数据存在和HDFS中的数据同步的问题。我们框架下的数据逻辑如下:
(1)数据同步(datasync):由于是adhoc查询场景,因此不会有从Alluxio写数据回hdfs的需求,所以data sync都是从HDFS->Alluxio
(2)元数据同步(metadatasync):在Alluxio之前,Hive表的location都是指向HDFS。为了能够增加对Alluxio schema的支持,又不会影响当前的离线业务,我们特意开发了一个metadata同步的工具,通过用户指定adhoc需要访问的白名单表,在每次该表有源数据和数据更新时,都会在秒级别自动同步到adhocmetastore同名的Hive表 - 其他配置和建议:
(1) Presto和Alluxio集成配置参见链接文档
(2)adhoc查询对网络吞吐的要求比较高,建议Presto+Alluxio所在的机器上双万兆bonding ethernet
(3)建议adhoc场景下的Hive表采用ORC+snappy的格式,利用ORC的列式存储和snappy的高压缩比,能够极大程度地减少Presto source stage数据输入的量和Alluxio的存储资源
相关性能测试
一、非Alluxio缓存场景下各SQL on Hadoop性能对比
- 数据量规模为: 1.5亿行,50个字段,46GB
- sql描述为
查询结果为:
可以看到,Presto的查询性能相比于前面几种方案存在着有较大的优势。
二、 Presto在有无Alluxio缓存情况下的单并发查询性能对比
(横坐标是查询时间节点,每隔1分钟进行一次查询;纵坐标是查询的时间,单位是ms)
上图中,绿线为Presto+Alluxio的查询性能曲线;红线为Presto + non Alluxio的查询性能曲线。从结果来看,有Alluxio Cache的查询时延有明显的优化,并且多次查询时间非常稳定。
发现的问题
在整个使用过程中,也发现了一些问题,下面是初步整理的一些:
- Alluxio组件性能相关的metrics没有暴露出来: 目前线上使用的是V1.7.1的版本,目前expose的metrics似乎都是Ops相关的指标,没有一些性能方便的metrics,比如workerthrift server的rpc请求延时,thrift server的线程情况,gc情况等。
- Alluxio的RPC性能还存在着优化的空间:从后续的一些多并发性能测试来看,偶尔会出现worker timeout的情况,猜测是和线程池配置有一定的关系。在社区规划中,Alluxio 2.0当中会有较大的升级。
- Alluxio master元数据的性能问题: 熟悉namenode的同学应该比较清楚,如果单个namenode的blocks和文件数超过一定的阈值的话,会导致系统性能出现下架,以及单点故障影响整体服务的风险。在我们内部,目前还是通过白名单的方式限制加载到alluxio里面的metadata的规模。目前社区规划在Alluxio2.0会支持到10亿个文件量级的元数据。
未来规划
目前在平台内部,已经有不少的交互式查询业务运行在上述的Presto+Alluxio框架上,很好地扩充了实时计算,离线计算之外的交互式查询业务场景的需求; 大多数情况下,alluxio都能提高查询的速度,所以后续会考虑更加广泛地部署服务并推广到更多的业务场景。与此同时,我们会更加积极地参与社区活动,关注alluxio在性能,稳定和业务尝试方面的工作。下一步的考虑具体来说:
- 测试Presto+Alluxio on yarn框架:目前的框架是独立于yarn的集群,由于adhoc业务的特殊性,其并发并不会特别高,所以会造成一定程度地资源浪费。而基于yarn的Presto+Alluxio则可以很好地解决该问题,也给更大范围的推广提供了可能。事实上,目前内部已经有基于yarn的Presto+Alluxio测试环境,正在进行功能和性能测试。
- 数据入库直接基于Alluxio统一文件入口。
- 和业务方探讨更多适合Alluxio读写的应用场景。
此外,特别感谢在这个过程中Alluxio社区的Maintainer范斌和开源社区各个小伙伴给予的支持!
作者简介:李爽(louShang)是网易游戏的大数据工程师,毕业于华南理工大学,目前主要专注于网易游戏OLAP数据仓库相关组件的维护和开发,例如Kylin/Presto等。另外,也同时关注HBase组件的维护,并促进组件相关解决方案在业务线的落地