作者简介
张巍,携程技术中心大数据资深研发工程师。2017年加入携程,在大数据平台部门从事基础框架的研发和运维,目前主要负责 Presto,Kylin,StructedStreaming 等大数据组建的运维,优化,设计及调研工作。对资源调度,OLAP引擎,存储引擎等大数据模块有浓厚的兴趣, 对 hdfs,yarn,presto,kylin,carbondata 等大数据组建有相关优化和改造经验。
一、背景介绍

携程作为中国在线旅游的龙头,提供酒店,机票,度假等服务,这些服务的背后是基于各个部门每天对海量数据的分析。
随着业务的不断增长,用户体验的不断提升,每个部门对数据处理的响应时间要求越来越短,对各个部门报表的响应速度要求越来越快,对跨部门的数据交互和查询也越来越紧密,所以需要一个统一的快速查询引擎,且这个查询引擎需要从GB到PB以上的海量数据集中获取有价值的信息。
我们在技术选型上对比了Presto,Spark,Impala等MPP数据库。综合考量框架本身性能和社区活跃程度,最终选择了Presto。
Presto是Facebook开源的MPP数据库,先简单了解下架构图:
它是一个Master-Slave的架构,由下面三部分组成:
-
一个Coordinator节点
-
一个Discovery Server节点
-
多个Worker节点
Coordinator负责解析SQL语句,生成执行计划,分发执行任务给Worker节点执行。
Discovery Server通常内嵌于Coordinator节点中。
Worker节点负责实际执行查询任务以及负责与HDFS交互读取数据。
Worker节点启动后向DiscoveryServer服务注册,Coordinator从DiscoveryServer获得可以正常工作的Worker节点。如果配置了HiveConnector,需要配置一个Hive MetaStore服务为Presto提供Hive元信息。
二、携程Presto使用的困境

首先来看一下我们2018年前遇到的一些问题。
携程在2014年探索使用Presto去满足用户快速即席查询和报表系统的需求。在2017年末,离线团队接手携程Presto后,发现当时的Presto本身存在一系列问题,那个时候Presto的版本是0.159,也相对较低。
稳定性差
-
当时用户反馈最多的是,Presto又OOM了。只能采取重启Presto恢复服务,实际上对于用户来说,系统挂掉是最恶劣的一种体验了。
-
Presto严格的分区类型检查和表类型检查,导致大量用户在Presto上发起的查询以失败告终,对于那些使用老分区重新刷数据的用户简直就是灾难。
-
一些大数据量的查询经常占用着计算资源,有时运行了2、3个小时,累计生成上百万个split,导致其他小的查询,响应速度受到严重影响。
认证不规范
-
很早以前,携程在Presto中内部嵌入一个Mysql的驱动, 通过在Mysql表中存放用户账号和密码访问Presto的权限认证。实际上和大数据团队整体使用Kerberos的策略格格不入。
性能浪费
-
所有的join查询默认都是使用Broadcast join,用户必须指定join模式才能做到Broadcast join 和 Map join的切换。
-
数据传输过程中并没有做压缩,从而带来网络资源的极大浪费。
没有监控
-
Presto自身没有监控分析系统,只能通过Presto自身提供的短时监控页面看到最近几分钟的用户查询记录,对分析和追踪历史错误查询带来很大的不便。
-
无法知道用户的查询量和用户的查询习惯,从而无法反馈给上游用户有效的信息,以帮助应用层开发人员更合理的使用Presto引擎。
三、携程Presto引擎上所做的改进

为了提供稳定可靠的Presto服务,我们在性能,安全,资源管控,兼容性,监控方面都做了一些改动,以下列出一些主要的改进点。
性能方面
-
根据Hive statistic信息,在执行查询之前分析hive扫描的数据,决定join查询是否采用Broadcast join还是map join。
-
Presto Page在多节点网络传输中开启压缩,减少Network IO的损耗,提高分布计算的性能。
-
通过优化Datanode的存储方式,减少presto扫描Datanode时磁盘IO带来的性能影响。
-
Presto自身参数方面的优化。
安全方面
-
启用Presto Kerberos模式,用户只能通过https安全协议访问Presto。
-
实现Hive Metastore Kerberos Impersonating 功能。
-
集成携程任务调度系统(宙斯)的授权规则。
-
实现Presto客户端Kerberos cache模式,简化Kerberos访问参数,同时减少和KDC交互。
资源管控方面
-
控制分区表最大查询分区数量限制。
-
控制单个查询生成split数量上限, 防止计算资源被恶意消耗。
-
自动发现并杀死长时间运行的查询。
兼容性方面
-
修复对Avro格式文件读取时丢失字段的情况。
-
兼容通过Hive创建 view,在Presto上可以对Hive view 做查询。(考虑到Presto和Hive语法的兼容性,目前能支持一些简单的view)。
-
去除Presto对于表字段类型和分区字段类型需要严格匹配的检测。
-
修复Alter table drop column xxx时出现ConcurrentModification问题。
四、携程Presto升级之路

升级之初Presto 的使用场景如图。
第一阶段,版本升级
对于版本选择,我们关心的几个问题:1)是否很好地解决各类内存泄漏的问题;2)对于查询的性能是否有一定提升。
综上考虑,决定使用0.190版本的Presto作为目标的升级版本。
通过这个版本的升级,结合对Presto的一部分改进,解决了几个主要问题:
-
Presto内存泄漏问题。
-
Presto读取Avro文件格式存在字段遗漏的问题。
-
Presto语法上无法支持整数类型相乘。
第二阶段,权限和性能优化
在第二个版本中,我们主要解决了以下问题:
-
Kerberos替换Mysql
-
Join模式的自动感知和切换
-
限流(拒绝返回100万以上数据量的查询)
认证机制
这里简单介绍下Kerberos权限替换过程中的一些细节。
Presto的认证流程:
Presto 涉及到认证和权限的部分如上面红色框标注的3个部分,Coordinator, HDFS和Hive Metastore这三块。Coordinator和HDFS这两块是比较完善的,重点讲一下Hive Metastore。
在Kerberos模式下,所有SQL都是用Presto的启动账号访问Hive Metastore,比如使用Hive账号启动Presto,不论是flt账户还是htl账户提交SQL,最终到Hive Metastore层面都是Hive账号,这样权限太大,存在安全风险。我们增加了Presto Hive MetastoreImpresonating机制,这样htl在访问Hive Metastore时使用的是通过Hive账号伪装的htl账户。
新的问题又来了,在认证过程中需要获取Hive的Token, 可是Token反复的获取都需要一次Metastore的交互,这样会给Metastore带来压力。于是我们对Token 做了一个缓存,在其Token有效期内缓存在Presto内存中。
第三阶段,资源管控和监控平台
在第三个版本中,我们解决了以下问题:
-
拦截大量生成split的查询SQL
-
Presto监控平台初步搭建
-
限制最大访问的分区数量
数据采集
流程图
程序每一分钟从Presto Coordinator采集数据, 分发到多个监听器,同时写入Mysql表。
当前入库5张监控表。
Basic query:查询基本信息(状态,内存使用,总时间消耗,错误信息等)
Query stats:查询性能信息(每一步的时间消耗,数据输入输出量信息等)
Query info:查询客户端参数信息(发起客户的基本信息,参数信息等)
Query stage info:每个查询中所有stage的信息(输入输出量信息,内存使用情况,调用核的数量等)
Query task info:每个stage中所有task的信息(输入输出信息, 内存信息,调用核数等)
实时健康状况报告
基于以上采集的数据,我们会实时生成presto集群的健康报表以及历史运行趋势。这些数据可以用于:
-
集群容量的评估
-
集群健康状态的检测
问题追踪
除了健康报表之外,对于查询错误和性能问题,我们提供了详细的历史数据, 运维人员可以通过报表反应出的异常状况做进一步的排查。
通过报表能够发现某个用户查询时出现了外部异常
通过查看异常堆栈,发现查询是由于hive metastore出现短暂重启引起的查询失败。
其他
在Presto升级改进的同时,我们也调研了Presto on Carbondata的使用场景。
当时Carbondata使用的是1.3.0版本。在此基础上:
-
修复了一系列Presto on carbon data 的功能和性能的问题
-
对比了Presto on carbon data 和Presto on hive,得出结论:Presto on Carbon整体性能和Presto on orc的整体性能相当。同样的数据量Carbon snappy的存储是ORC zlib的六倍,就目前存储吃紧的情况下,不适合使用。
-
目前仅在线上提供Carbondata 连接器,暂未投入业务使用。
当前Presto的架构为:
五、携程Presto未来升级方向

架构完善和技术改进
-
启用Presto资源队列,规划通过AppName划分每个资源队列的最大查询并发数, 避免某个应用大量的查询并发同时被Presto执行,从而影响其他的App。
-
实时告警平台,对于错误的查询,Presto能够实时的发送异常查询到告警平台,帮助运维人员快速响应和发现错误以便及时处理。
-
统一的查询引擎,统一的查询引擎可以在presto,kylin,hive spark-sql之间匹配最优的查询引擎,做语法转换后路由过去。
业务方向
-
未来携程内部OLAP报表系统(Art Nova) 会更大范围的采用携程Presto作为用户自定义报表的底层查询引擎,以用来提高报表的响应速度和用户体验。
-
部分业务部门的vdp也计划调研,实时数据计算采用Presto作为其默认的查询引擎的可能性。
下个阶段我们期望的Presto整体架构图:
六、结束语

随着Presto社区的蓬勃发展,最新版本为0.203,其中包含了大量的优化和Bug Fix,希望跟大家一起讨论。
【推荐阅读】