Closed vieyahn2017 closed 5 months ago
Presto是一个分布式SQL查询引擎, 它被设计为用来专门进行高速、实时的数据分析。它支持标准的ANSI SQL,包括复杂查询、聚合(aggregation)、连接(join)和窗口函数(window functions)。
下面的架构图中展现了简化的Presto系统架构。客户端(client)将SQL查询发送到Presto的协调员(coordinator)。协调员会进行语法检查、分析和规划查询计划。计划员(scheduler)将执行的管道组合在一起, 将任务分配给那些里数据最近的节点,然后监控执行过程。 客户端从输出段中将数据取出, 这些数据是从更底层的处理段中依次取出的。
Presto的运行模型和Hive或MapReduce有着本质的区别。Hive将查询翻译成多阶段的MapReduce任务, 一个接着一个地运行。 每一个任务从磁盘上读取输入数据并且将中间结果输出到磁盘上。 然而Presto引擎没有使用MapReduce。它使用了一个定制的查询和执行引擎和响应的操作符来支持SQL的语法。除了改进的调度算法之外, 所有的数据处理都是在内存中进行的。 不同的处理端通过网络组成处理的流水线。 这样会避免不必要的磁盘读写和额外的延迟。 这种流水线式的执行模型会在同一时间运行多个数据处理段, 一旦数据可用的时候就会将数据从一个处理段传入到下一个处理段。 这样的方式会大大的减少各种查询的端到端响应时间。
Presto系统是用Java来实现的, 主要原因是Java的开发效率高,且拥有非常好的生态环境, 并且很容易同Facebook数据基础设施的其他Java应用进行集成。Presto会将查询计划中的一部分动态地编译成JVM字节代码,并让JVM优化和生成原生的机器代码。 通过谨慎地使用内存和数据结构,Presto避免了通常Java程序会碰到的内存分配和垃圾收集(Java garbage collection)的问题。(在后一篇文章中, 我们会分享一些在开发高性能Java系统的时候的一些提示和技巧,以及我们在搭建Presto系统时的一些经验教训。)
扩展性是在设计Presto时的另一个要点。在项目的早期阶段, 我们就意识到出了HDFS之外,大量数据会被存储在很多其他类型的系统中。 其中一些是像HBase一类的为人熟知的系统,另一类则是象Facebook New Feed一样的定制的后台。Presto设计了一个简单的数据存储的抽象层, 来满足在不同数据存储系统之上都可以使用SQL进行查询。存储插件(连接器,connector)只需要提供实现以下操作的接口, 包括对元数据(metadata)的提取,获得数据存储的位置,获取数据本身的操作等。除了我们主要使用的Hive/HDFS后台系统之外, 我们也开发了一些连接其他系统的Presto 连接器,包括HBase,Scribe和定制开发的系统。
(译者注:Scribe是Facebook的开源项目,可以实时的将大量服务器产生的日志文件汇总到文件系统中, 详见:https://github.com/facebook/scribe)
(译者注: 从目前的信息来看,Presto的架构在分布式处理数据的方式和基于MapReduce 2.0的HorntonWorks的Stinger有着很大的不同,可能会比较接近于Google的Dremel或者Cloudera的Impala。 )
Presto 是 Facebook 推出的一个基于Java开发的大数据分布式 SQL 查询引擎,可对从数 G 到数 P 的大数据进行交互式的查询,查询的速度达到商业数据仓库的级别,据称该引擎的性能是 Hive 的 10 倍以上。Presto 可以查询包括 Hive、Cassandra 甚至是一些商业的数据存储产品,单个 Presto 查询可合并来自多个数据源的数据进行统一分析。Presto 的目标是在可期望的响应时间内返回查询结果,Facebook 在内部多个数据存储中使用 Presto 交互式查询,包括 300PB 的数据仓库,超过 1000 个 Facebook 员工每天在使用 Presto 运行超过 3 万个查询,每天扫描超过 1PB 的数据。
presto架构
presto低延迟原理
presto存储插件
presto执行过程
presto引擎对比
Presto查询引擎是一个Master-Slave的架构,由下面三部分组成: 一个Coordinator节点 一个Discovery Server节点 多个Worker节点 Coordinator: 负责解析SQL语句,生成执行计划,分发执行任务给Worker节点执行 Discovery Server: 通常内嵌于Coordinator节点中 Worker节点: 负责实际执行查询任务,负责与HDFS交互读取数据 Worker节点启动后向Discovery Server服务注册,Coordinator从Discovery Server获得可以正常工作的Worker节点。如果配置了Hive Connector,需要配置一个Hive MetaStore服务为Presto提供Hive元信息 更形象架构图如下:
完全基于内存的并行计算 流水线式计算作业 本地化计算 动态编译执行计划 GC控制
Presto设计了一个简单的数据存储的抽象层, 来满足在不同数据存储系统之上都可以使用SQL进行查询。 存储插件(连接器,connector)只需要提供实现以下操作的接口, 包括对元数据(metadata)的提取,获得数据存储的位置,获取数据本身的操作等。 除了我们主要使用的Hive/HDFS后台系统之外, 我们也开发了一些连接其他系统的Presto 连接器,包括HBase,Scribe和定制开发的系统 插件结构图如下:
执行过程示意图:
提交查询:用户使用Presto Cli提交一个查询语句后,Cli使用HTTP协议与Coordinator通信,Coordinator收到查询请求后调用SqlParser解析SQL语句得到Statement对象,并将Statement封装成一个QueryStarter对象放入线程池中等待执行,如下图:示例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;
逻辑执行过程示意图如下:
上图逻辑执行计划图中的虚线就是Presto对逻辑执行计划的切分点,逻辑计划Plan生成的SubPlan分为四个部分,每一个SubPlan都会提交到一个或者多个Worker节点上执行 SubPlan有几个重要的属性planDistribution、outputPartitioning、partitionBy属性整个执行过程的流程图如下: PlanDistribution:表示一个查询阶段的分发方式,上图中的4个SubPlan共有3种不同的PlanDistribution方式 Source:表示这个SubPlan是数据源,Source类型的任务会按照数据源大小确定分配多少个节点进行执行 Fixed: 表示这个SubPlan会分配固定的节点数进行执行(Config配置中的query.initial-hash-partitions参数配置,默认是8) None: 表示这个SubPlan只分配到一个节点进行执行 OutputPartitioning:表示这个SubPlan的输出是否按照partitionBy的key值对数据进行Shuffle(洗牌), 只有两个值HASH和NONE
在上图的执行计划中,SubPlan1和SubPlan0 PlanDistribution=Source,这两个SubPlan都是提供数据源的节点,SubPlan1所有节点的读取数据都会发向SubPlan0的每一个节点;SubPlan2分配8个节点执行最终的聚合操作;SubPlan3只负责输出最后计算完成的数据,如下图:
SubPlan1和SubPlan0 作为Source节点,它们读取HDFS文件数据的方式就是调用的HDFS InputSplit API,然后每个InputSplit分配一个Worker节点去执行,每个Worker节点分配的InputSplit数目上限是参数可配置的,Config中的query.max-pending-splits-per-node参数配置,默认是100 SubPlan1的每个节点读取一个Split的数据并过滤后将数据分发给每个SubPlan0节点进行Join操作和Partial Aggr操作 SubPlan0的每个节点计算完成后按GroupBy Key的Hash值将数据分发到不同的SubPlan2节点 所有SubPlan2节点计算完成后将数据分发到SubPlan3节点 SubPlan3节点计算完成后通知Coordinator结束查询,并将数据发送给Coordinator
与hive、SparkSQL对比结果图
Presto是Facebook设计的开源分布式的SQL查询引擎,支持关系型和非关系型多种数据源。Presto有以下 特点:
1.完全内存并行。Presto所有的数据处理都是在内存中进行的,在同一时间运行多个数据处理段,一旦数据可用就会将数据从一个处理段传入到下一个处理段。这样的方式会大大的减少各种查询的端到端响应时间。(不适合大面积聚合任务)
2.没有容错机制,一个task失败就会导致整个查询失败,内存不够就直接OOM。(SparkSQL内存不够就写磁盘,presto直接OOM)
3.支持WebUI,AirPal是AirBnb开源的查询Presto的WebUI。
产生背景:Facebook的科学家和分析师一直依靠Hive来做数据分析。但Hive使用MapReduce作为底层计算框架,是专为批处理设计的。但随着数据越来越多,使用Hive进行一个简单的数据查询可能要花费几分到几小时,显然不能满足交互式查询的需求。Facebook也调研了其他比Hive更快的工具,但它们要么在功能有所限制要么就太简单,以至于无法操作Facebook庞大的数据仓库。(用来替代hive做简单的数据查询)
Presto系统架构:
上图中展现了Presto的系统架构。客户端(client)将SQL查询发送到Presto的协调员(coordinator)。协调员会进行语法检查、分析和规划查询计划。计划员(scheduler)将执行的管道组合在一起, 将任务分配给那些里数据最近的Worker,然后监控执行过程。 最终客户端将执行结果从更底层的处理段中依次取出,显示给用户。
作用:
1.性能约为Hive的10倍
2.快速响应的分布式交互式查询
3.支持多种数据源
总结:presto适合GB级数据的短期交互式查询,而SparkSQL/Hive适合复杂长期的离线任务。presto使用纯内存工作,没有容错,一个task失败就整个任务查询失败。
这里给出美团公司内部开放给分析师、PM、工程师进行自助查询的查询中心的一个测试报告。这里选取了平时的5000个Hive查询,通过Presto查询的对比见下面的表格。
自助查询sql数 | hive | presto | presto/hive |
---|---|---|---|
1424 | 154427s | 27708s | 0.179424582489 |
Presto:Facebook的分布式SQL查询引擎 https://blog.csdn.net/bigdatahappy/article/details/39928125