分析Facebook的数据信息库查寻模块Presto在美团的运

2021-02-21 10:54 admin

Facebook的数据信息库房储存在小量大中型Hadoop/HDFS群集。Hive是Facebook在几年前专为Hadoop打造的1款数据信息库房专用工具。在之前,Facebook的科学研究家和剖析师1直借助Hive来做数据信息剖析。但Hive应用MapReduce做为最底层测算架构,是专为批解决设计方案的。但伴随着数据信息愈来愈多,应用Hive开展1个简易的数据信息查寻将会要花销几分到几小时,明显不可以考虑互动式查寻的要求。Facebook也调查了别的比Hive更快的专用工具,但它们要末在作用有一定的限定要末就太简易,以致于没法实际操作Facebook巨大的数据信息库房。

2012年刚开始试用的1些外界新项目都不符合适,她们决策自身开发设计,这便是Presto。2012年秋天刚开始开发设计,现阶段该新项目早已在超出 1000名Facebook雇员中应用,运作超出30000个查寻,每天数据信息在1PB级別。Facebook称Presto的特性比Hive好些上10倍多。2013年Facebook宣布公布开源系统Presto。

本文最先详细介绍Presto从客户递交SQL到实行的这1个全过程,随后尝试对Presto完成即时查寻的基本原理开展剖析和总结,最终详细介绍Presto在美团的应用状况。

Presto构架

Presto查寻模块是1个Master-Slave的构架,由1个Coordinator连接点,1个Discovery Server连接点,好几个Worker连接点构成,Discovery Server一般嵌入于Coordinator连接点中。Coordinator负责分析SQL句子,转化成实行方案,派发实行每日任务给Worker连接点实行。Worker连接点负责具体实行查寻每日任务。Worker连接点起动后向Discovery Server服务申请注册,Coordinator从Discovery Server得到能够一切正常工作中的Worker连接点。假如配备了Hive Connector,必须配备1个Hive MetaStore服务为Presto出示Hive元信息内容,Worker连接点与HDFS互动载入数据信息。

Presto实行查寻全过程简介
既然Presto是1个互动式的查寻模块,大家最关注的便是Presto完成低延时查寻的基本原理,我觉得关键是下面几个重要点,自然也有1些传统式的SQL提升基本原理,这里不详细介绍了。

彻底根据运行内存的并行处理测算
流水线
当地化测算
动态性编译程序实行方案
当心应用运行内存和数据信息构造
类BlinkDB的近似查寻
GC操纵
以便详细介绍上述几个关键点,这里先详细介绍1下Presto实行查寻的全过程

递交查寻
客户应用Presto Cli递交1个查寻句子后,Cli应用HTTP协议书与Coordinator通讯,Coordinator收到查寻恳求后启用SqlParser分析SQL句子获得Statement目标,并将Statement封裝成1个QueryStarter目标放入进程池中等候实行。

SQL编译程序全过程
Presto与Hive1样,应用Antlr撰写SQL英语的语法,英语的语法标准界定在Statement.g和StatementBuilder.g两个文档中。
以下图中所示从SQL编译程序为最后的物理学实行方案大约分成5部,最后转化成在每一个Worker连接点上运作的LocalExecutionPlan,这里不详尽详细介绍SQL分析为逻辑性实行方案的全过程,根据1个SQL句子来了解查寻方案转化成以后的测算全过程。

样例SQL:

拷贝编码
编码以下:
select c1.rank, count(*) from dim.city c1 join dim.city c2 on c1.id = c2.id where c1.id > 10 group by c1.rank limit 10;

上面的SQL句子转化成的逻辑性实行方案Plan如上图所示。那末Presto是怎样对上面的逻辑性实行方案开展拆分以较高的并行处理度去实行完这个方案呢,大家看来看物理学实行方案。

物理学实行方案
逻辑性实行方案图中的虚线便是Presto对逻辑性实行方案的分割点,逻辑性方案Plan转化成的SubPlan分成4个一部分,每个SubPlan都会递交到1个或好几个Worker连接点上实行。

SubPlan有几个关键的特性planDistribution、outputPartitioning、partitionBy特性。

PlanDistribution表明1个查寻Stage的派发方法,逻辑性实行方案图中的4个SubPlan共有3种不一样的PlanDistribution方法:Source表明这个SubPlan是数据信息源,Source种类的每日任务会依照数据信息源尺寸明确分派是多少个连接点开展实行;Fixed表明这个SubPlan会分派固定不动的连接点数开展实行(Config配备中的query.initial-hash-partitions主要参数配备,默认设置是8);None表明这个SubPlan只分派到1个连接点开展实行。在下面的实行方案中,SubPlan1和SubPlan0 PlanDistribution=Source,这两个SubPlan全是出示数据信息源的连接点,SubPlan1全部连接点的载入数据信息都会发向SubPlan0的每个连接点;SubPlan2分派8个连接点实行最后的汇聚实际操作;SubPlan3只负责輸出最终测算进行的数据信息。
OutputPartitioning特性仅有两个值HASH和NONE,表明这个SubPlan的輸出是不是依照partitionBy的key值对数据信息开展Shuffle。在下面的实行方案中仅有SubPlan0的OutputPartitioning=HASH,因此SubPlan2接受到的数据信息是依照rank字段Partition后的数据信息。

彻底根据运行内存的并行处理测算
查寻的并行处理实行步骤
Presto SQL的实行步骤以下图所示

Cli根据HTTP协议书递交SQL查寻以后,查寻恳求封裝成1个SqlQueryExecution目标交到Coordinator的SqlQueryManager#queryExecutor进程池去实行
每一个SqlQueryExecution进程(图中Q-X进程)起动后对查寻恳求的SQL开展英语的语法分析和提升并最后转化成好几个Stage的SqlStageExecution每日任务,每一个SqlStageExecution每日任务依然交到一样的进程池去实行
每一个SqlStageExecution进程(图中S-X进程)起动后每一个Stage的每日任务按PlanDistribution特性结构1个或好几个RemoteTask根据HTTP协议书分派给远端Worker连接点实行
Worker连接点接受到RemoteTask恳求以后,起动1个SqlTaskExecution进程(图中T-X进程)将这个每日任务的每一个Split包装成1个PrioritizedSplitRunner每日任务(图中SR-X)交到Worker连接点的TaskExecutor#executor进程池去实行

上面的实行方案具体实行实际效果以下图所示。

Coordinator根据HTTP协议书启用Worker连接点的 /v1/task 插口将实行方案分派给全部Worker连接点(图中蓝色箭头)
SubPlan1的每一个连接点载入1个Split的数据信息并过虑后将数据信息派发给每一个SubPlan0连接点开展Join实际操作和Partial Aggr实际操作
SubPlan1的每一个连接点测算进行后按GroupBy Key的Hash值将数据信息派发到不一样的SubPlan2连接点
全部SubPlan2连接点测算进行后将数据信息派发到SubPlan3连接点
SubPlan3连接点测算进行后通告Coordinator完毕查寻,并将数据信息推送给Coordinator

源数据信息的并行处理载入
在上面的实行方案中SubPlan1和SubPlan0全是Source连接点,实际上它们载入HDFS文档数据信息的方法便是启用的HDFS InputSplit API,随后每一个InputSplit分派1个Worker连接点去实行,每一个Worker连接点分派的InputSplit数目上限是主要参数可配备的,Config中的query.max-pending-splits-per-node主要参数配备,默认设置是100。

遍布式的Hash汇聚
上面的实行方案在SubPlan0中会开展1次Partial的汇聚测算,测算每一个Worker连接点载入的一部分数据信息的一部分汇聚結果,随后SubPlan0的輸出会依照group by字段的Hash值分派不一样的测算连接点,最终SubPlan3合拼全部結果并輸出

流水线
数据信息实体模型
Presto中解决的最少数据信息模块是1个Page目标,Page目标的数据信息构造以下图所示。1个Page目标包括好几个Block目标,每一个Block目标是1个字节数字能量数组,储存1个字段的若干行。好几个Block横切的1行是真正的1行数据信息。1个Page最大1MB,数最多16*1024行数据信息。

连接点內部流水线测算
下图是1个Worker连接点內部的测算步骤图,左边是每日任务的实行步骤图。

Worker连接点将最细粒度的每日任务封裝成1个PrioritizedSplitRunner目标,放入pending split优先选择级序列中。每一个

Worker连接点起动1定数目地进程开展测算,进程数task.shard.max-threads=availableProcessors() * 4,在config中配备。

每一个空余的进程从序列中取下1个PrioritizedSplitRunner目标实行,假如实行进行1个周期,超出最大实行時间1秒钟,分辨每日任务是不是实行进行,假如进行,从allSplits序列中删掉,假如沒有,则放回pendingSplits序列中。

每一个每日任务的实行步骤以下图右边,先后遍历全部Operator,尝试从上1个Operator取1个Page目标,假如获得的Page不为空,交到下1个Operator实行。

连接点间流水线测算
下图是ExchangeOperator的实行步骤图,ExchangeOperator为每个Split起动1个HttpPageBufferClient目标,积极向上1个Stage的Worker连接点拉数据信息,数据信息的最少企业也是1个Page目标,取到数据信息后放入Pages序列中

当地化测算
Presto在挑选Source每日任务测算连接点的情况下,针对每个Split,按下面的对策挑选1些minCandidates

优先选择挑选与Split同1个Host的Worker连接点
假如连接点不足优先选择挑选与Split同1个Rack的Worker连接点
假如连接点还不足任意挑选别的Rack的连接点
针对全部Candidate连接点,挑选assignedSplits至少的连接点。

动态性编译程序实行方案
Presto会将实行方案中的ScanFilterAndProjectOperator和FilterAndProjectOperator动态性编译程序为Byte Code,并交到JIT去编译程序为native编码。Presto也应用了Google Guava出示的LoadingCache缓存文件转化成的Byte Code。

上面的每段编码片断中,第1段为沒有动态性编译程序前的编码,第2段编码为动态性编译程序转化成的Byte Code反编译程序以后复原的提升代
码,大家看到这里选用了循环系统进行的提升方式。

循环系统进行最常见来减少循环系统花销,为具备好几个作用模块的解决器出示命令级并行处理。也是有利于命令流水线的生产调度。

当心应用运行内存和数据信息构造
应用Slice开展运行内存实际操作,Slice应用Unsafe#copyMemory完成了高效率的运行内存复制,Slice库房参照:https://github.com/airlift/slice

Facebook工程项目师在另外一篇详细介绍ORCFile提升的文章内容中也提到应用Slice将ORCFile的写特性提升了20%~30%,参照:https://code.facebook.com/posts/229861827208629/scaling-the-facebook-data-warehouse-to⑶00-pb/

类BlinkDB的近似查寻
以便加速avg、count distinct、percentile等汇聚涵数的查寻速率,Presto精英团队与BlinkDB作者之1Sameer Agarwal协作引进了1些近似查寻涵数approx_avg、approx_distinct、approx_percentile。approx_distinct应用HyperLogLog Counting优化算法完成。

GC操纵
Presto精英团队在应用hotspot java7时发现了1个JIT的BUG,当今码缓存文件快要做到上限时,JIT将会会终止工作中,从而没法将应用频率高的编码动态性编译程序为native编码。

Presto精英团队应用了1个较为Hack的方式去处理这个难题,提升1个进程在编码缓存文件做到70%以上时开展显式GC,使得早已载入的Class从perm中移除,防止JIT没法一切正常工作中的BUG。

美团怎样应用Presto
挑选presto的缘故
2013年大家也用过1段時间的impala,那时候impala不适用网上1.x的hadoop小区版,因此搭了1个CDH的小群集,每日将大群集的网络热点数据信息导入小群集。可是hadoop群集年前进行升級2.2以后,那时候的impala还不适用2.2 hadoop版本号。而Presto恰好刚开始适用2.x hadoop小区版,而且Presto在Facebook 300PB绝大多数据量的自然环境下能够取得成功的获得很多应用,大家坚信它在美团还可以很好的支撑点大家即时剖析的要求,因而决策先上线检测应用1段時间。

布署和应用方式
考虑到到两个缘故:1、因为Hadoop群集关键是晚间进行昨日的测算每日任务,大白天除系统日志写入外,群集的测算负载较低。2、Presto Worker连接点与DataNode连接点布局在1台设备上能够当地测算。因而大家将Presto布署到了全部的DataNode设备上,而且晚间终止Presto服务,防止占有群集資源,晚间基础也不容易有效户查寻数据信息。

Presto2次开发设计和BUG修补
年后才宣布上线Presto查寻模块,0.60版本号,应用的時间不长,可是也遇到了1些难题:

美团的Hadoop应用的是2.2版本号,而且打开了Security方式,可是Presto不适用Kerberos验证,大家改动了Presto编码,提升了Kerberos验证的作用。
Presto还不适用SQL的隐式种类变换,而Hive适用,许多自助查寻的客户习惯性了Hive,致使应用Presto时都会出現表述式中上下自变量种类不配对的难题,大家提升了隐式种类变换的作用,大大减小了客户SQL错误的几率。
Presto不适用查寻lzo缩小的数据信息,必须改动hadoop-lzo的编码。
处理了1个having子句中有distinct字段时查寻不成功的BUG,并意见反馈了Presto精英团队 https://github.com/facebook/presto/pull/1104
全部编码的改动能够参照大家在github上的库房 https://github.com/MTDATA/presto/commits/mt-0.60

具体应用实际效果
这里得出1个企业內部对外开放给剖析师、PM、工程项目师开展自助查寻的查寻管理中心的1个检测汇报。这里选择了平常的5000个Hive查寻,根据Presto查寻的比照见下面的报表。