Presto在滴滴的探索与实践
文章作者:armsword 滴滴研发工程师
内容来源:滴滴技术
序曲:Presto在滴滴内部发展三年,已经成为滴滴内部Ad-Hoc和Hive SQL加速的首选引擎。目前服务6K+用户,每天读取2PB ~ 3PB HDFS数据,处理30万亿~35万亿条记录,为了承接业务及丰富使用场景,滴滴Presto需要解决稳定性、易用性、性能、成本等诸多问题。我们在3年多的时间里,做了大量优化和二次开发,积攒了非常丰富的经验。本文分享了滴滴对Presto引擎的改进和优化,同时也提供了大量稳定性建设经验。
Presto简介
02
Presto在滴滴的应用
Hive SQL查询加速 数据平台Ad-Hoc查询 报表(BI报表、自定义报表) 活动营销 数据质量检测 资产管理 固定数据产品
03
PrestoSQL社区活跃度更高,PR和用户问题能够及时回复 PrestoDB主要主力还是Facebook维护,以其内部需求为主 PrestoDB未来方向主要是ETL相关的,我们有Spark兜底,ETL功能依赖Spark、Hive
04
引擎改进
latency高,QPS较低 不能查实时数据,如果有实时数据需求,需要再构建一条实时数据链路,增加了系统的复杂性 要想获得极限性能,必须与HDFS DataNode 混部,且DataNode使用高级硬件,有自建HDFS的需求,增加了运维的负担
结合 Druid 的预聚合、计算能力(过滤聚合)、Cache能力,提升Presto性能(RT与QPS) 让 Presto 具备查询 Druid 实时数据能力 为Druid提供全面的SQL能力支持,扩展Druid数据的应用场景 通过Druid Broker获取Druid元数据信息 从Druid Historical直接获取数据 实现了Limit下推、Filter下推、Project下推及Agg下推
无法划分多个Split,查询性能差 请求查询Broker,之后再查询Historical,多一次网络通信 对于一些场景,如大量Scan场景,会导致Broker OOM Project及Agg下推支持不完善
租户与权限 与内部Hadoop打通,使用HDFS SIMPLE协议做认证 使用Ranger做鉴权,解析SQL使Presto拥有将列信息传递给下游的能力,提供用户名+数据库名/表名/列名,四元组的鉴权能力,同时提供多表同时鉴权的能力 用户指定用户名做鉴权和认证,大账号用于读写HDFS数据 支持视图、表别名鉴权
语法拓展 支持add partition 支持数字开头的表 支持数字开头的字段
特性增强 insert数据时,将插入数据的总行数写入HMS,为业务方提供毫秒级的元数据感知能力 支持查询进度滚动更新,提升了用户体验 支持查询可以指定优先级,为用户不同等级的业务提供了优先级控制的能力 修改通信协议,支持业务方可以传达自定义信息,满足了用户的日志审计需要等 支持DeprecatedLzoTextInputFormat格式 支持读HDFS Parquet文件路径
通过Presto Plugin实现日志审计功能 通过JMX获取引擎指标将监控信息写入Ganglia 将日志审计采集到HDFS和ES;统一接入运维监控体系,将所有指标发到 Kafka; Presto UI改进:可以查看Worker信息,可以查看Worker死活信息
在Presto交流社区,Presto的稳定性问题困扰了很多Presto使用者,包括Coordinator和Worker挂掉,集群运行一段时间后查询性能变慢等。我们在解决这些问题时积累了很多经验,这里说下解决思路和方法。
根据职责划分,Presto分为Coordinator和Worker模块,Coordinator主要负责SQL解析、生成查询计划、Split调度及查询状态管理等,所以当Coordinator遇到OOM或者Coredump时,获取元信息及生成Splits是重点怀疑的地方。而内存问题,推荐使用MAT分析具体原因。如下图是通过MAT分析,得出开启了FileSystem Cache,内存泄漏导致OOM。
使用HDFS FileSystem Cache导致内存泄漏,解决方法禁止FileSystem Cache,后续Presto自己维护了FileSystem Cache Jetty导致堆外内存泄漏,原因是Gzip导致了堆外内存泄漏,升级Jetty版本解决 Splits太多,无可用端口,TIME_WAIT太高,修改TCP参数解决 JVM Coredump,显示'unable to create new native thread',通过修改pid_max及max_map_count解决 Presto内核Bug,查询失败的SQL太多,导致Coordinator内存泄漏,社区已修复
通过Resource Group控制业务并发,防止严重超卖 通过JVM调优,解决一些常见内存问题,如Young GC Exhausted 善用MAT工具,发现内存瓶颈
Sys load过高,导致业务查询性能影响很大,研究jvm原理,通过参数(-XX:PerMethodRecompilationCutoff=10000 及 -XX:PerBytecodeRecompilationCutoff=10000)解决,也可升级最新JVM解决 Worker查询hang住问题,原因HDFS客户端存在bug,当Presto与HDFS混部署,数据和客户端在同一台机器上时,短路读时一直wait锁,导致查询Hang住超时,Hadoop社区已解决 超卖导致Worker Young GC Exhausted,优化GC参数,如设置-XX:G1ReservePercent=25 及 -XX:InitiatingHeapOccupancyPercent=15 ORC太大,导致Presto读取ORC Stripe Statistics出现OOM,解决方法是限制ProtoBuf报文大小,同时协助业务方合理数据治理 修改Presto内存管理逻辑,优化Kill策略,保障当内存不够时,Presto Worker不会OOM,只需要将大查询Kill掉,后续熔断机制会改为基于JVM,类似ES的熔断器,比如95% JVM 内存时,Kill掉最大SQL
某业务集群进行了JVM调优,将Ref Proc由单线程改为并行执行,普通查询由30S~1分钟降低为3-4S,性能提升10倍+ ORC数据优化,将指定string字段添加了布隆过滤器,查询性能提升20-30%,针对一些业务做了调优 数据治理和小文件合并,某业务方查询性能由20S降低为10S,性能提升一倍,且查询性能稳定 ORC格式性能优化,查询耗时减少5% 分区裁剪优化,解决指定分区但获取所有分区元信息问题,减少了HMS的压力 下推优化,实现了Limit、Filter、Project、Agg下推到存储层
Presto on Alluxio查询性能提升35%,但是内存占用和性能提升不成正比,所以我们放弃了Presto on Alluxio,后续可能会对一些性能要求敏感的业务使用 Presto on Carbondata是在18年8月份测试的,当时的版本,Carbondata稳定性较差,性能没有明显优势,一些场景ORC更快,所以我们没有再继续跟踪调研Presto on Carbondata。因为滴滴有专门维护Druid的团队,所以我们对接了Presto on Druid,一些场景性能提升4~5倍,后续我们会更多关注Presto on Clickhouse及Presto on Elasticsearch
05
总结
通过以上工作,滴滴Presto逐渐接入公司各大数据平台,并成为了公司首选Ad-Hoc查询引擎及Hive SQL加速引擎,下图可以看到某产品接入后的性能提升:
上图可以看到大约2018年10月该平台开始接入Presto,查询耗时TP50性能提升了10+倍,由400S降低到31S。且在任务数逐渐增长的情况下,查询耗时保证稳定不变。
而高性能集群,我们做了很多稳定性和性能优化工作,保证了平均查询时间小于2S。如下图所示:
06
展望
但是如果看最近一个月的CPU使用率会发现,平均CPU使用率比较低,且波峰在白天10~18点,晚上基本上没有查询,CPU使用率不到5%。如下图所示:
所以,解决晚上资源浪费问题是我们今后需要解决的难题。
同时,为了不与开源社区脱节,我们打算升级PrestoDB 0.215到PrestoSQL 340版本,届时会把我们的Presto on Druid代码开源出来,回馈社区。