Presto架构及原理

wdsu5225 8年前
   <p>Presto 是 非死book 推出的一个基于Java开发的大数据分布式 SQL 查询引擎,可对从数 G 到数 P 的大数据进行交互式的查询,查询的速度达到商业数据仓库的级别,据称该引擎的性能是 Hive 的 10 倍以上。Presto 可以查询包括 Hive、Cassandra 甚至是一些商业的数据存储产品,单个 Presto 查询可合并来自多个数据源的数据进行统一分析。Presto 的目标是在可期望的响应时间内返回查询结果,非死book 在内部多个数据存储中使用 Presto 交互式查询,包括 300PB 的数据仓库,超过 1000 个 非死book 员工每天在使用 Presto 运行超过 3 万个查询,每天扫描超过 1PB 的数据。</p>    <h3><strong>目录:</strong></h3>    <ul>     <li> <p>presto架构</p> </li>     <li> <p>presto低延迟原理</p> </li>     <li> <p>presto存储插件</p> </li>     <li> <p>presto执行过程</p> </li>     <li> <p>presto引擎对比</p> </li>    </ul>    <h3><strong>Presto架构</strong></h3>    <p style="text-align: center;"><strong><img src="https://simg.open-open.com/show/c1842f569b056c8652c53a7e8c589ac2.png"> </strong></p>    <ul>     <li> <p>Presto查询引擎是一个 Master-Slave 的架构,由下面三部分组成:</p>      <ol>       <li> <p>一个Coordinator节点</p> </li>       <li> <p>一个Discovery Server节点</p> </li>       <li> <p>多个Worker节点</p> </li>      </ol> </li>     <li> <p>Coordinator: 负责解析SQL语句,生成执行计划,分发执行任务给Worker节点执行</p> </li>     <li> <p>Discovery Server: 通常内嵌于Coordinator节点中</p> </li>     <li> <p>Worker节点: 负责实际执行查询任务,负责与HDFS交互读取数据</p> </li>     <li> <p>Worker节点启动后 向Discovery Server服务注册 ,Coordinator从Discovery Server获得可以正常工作的Worker节点。如果配置了Hive Connector,需要配置一个Hive MetaStore服务为Presto提供Hive元信息</p> </li>     <li> <p>更形象架构图如下:</p> </li>    </ul>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/f8c98d1ee369ffc231149f31c348b30c.png"></p>    <h3><strong>Presto低延迟原理</strong></h3>    <ul>     <li> <p>完全基于内存的并行计算</p> </li>     <li> <p>流水线式计算作业</p> </li>     <li> <p>本地化计算</p> </li>     <li> <p>动态编译执行计划</p> </li>     <li> <p>GC控制</p> </li>    </ul>    <h3><strong>Presto存储插件</strong></h3>    <ul>     <li> <p>Presto设计了一个简单的 数据存储的抽象层 , 来满足在不同数据存储系统之上都可以使用SQL进行查询。</p> </li>     <li> <p>存储插件(连接器,connector)只需要提供实现以下操作的接口, 包括对 元数据(metadata)的提取 ,获得 数据存储的位置 ,获取 数据本身的操作 等。</p> </li>     <li> <p>除了我们主要使用的Hive/HDFS后台系统之外, 我们也开发了一些连接其他系统的Presto 连接器,包括HBase,Scribe和定制开发的系统</p> </li>     <li> <p>插件结构图如下:</p> </li>    </ul>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/d4e0e4f221a2a8425e91d93dc78bccd7.png"></p>    <h3><strong>presto执行过程</strong></h3>    <ul>     <li> <p>执行过程示意图:</p> </li>    </ul>    <p style="text-align: center;"><strong><img src="https://simg.open-open.com/show/bf377f59f5719d8f2c185fde7a4d6f6c.png"> </strong></p>    <ul>     <li> <p><strong>提交查询:</strong> 用户使用Presto Cli提交一个查询语句后,Cli使用HTTP协议与Coordinator通信,Coordinator收到查询请求后调用SqlParser解析SQL语句得到Statement对象,并将Statement封装成一个QueryStarter对象放入线程池中等待执行,如下图:示例SQL如下</p>      <ul>       <li style="text-align: center;"><img src="https://simg.open-open.com/show/094cb95d0997a0d8f73e798188078b89.png"></li>      </ul> </li>     <li> <pre>  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;  </pre> </li>     <li>逻辑执行过程示意图如下:</li>    </ul>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/90ff9ac50e1e883ac3c289067cfc0fb8.png">​​​​​​​</p>    <ul>     <li> <p>上图逻辑执行计划图中的虚线就是Presto对逻辑执行计划的切分点,逻辑计划Plan生成的SubPlan分为四个部分,每一个SubPlan都会提交到一个或者多个Worker节点上执行</p> </li>     <li> <p>SubPlan有几个重要的属性planDistribution、outputPartitioning、partitionBy属性整个执行过程的流程图如下:</p>      <ol>       <li> <p>PlanDistribution:表示一个查询阶段的分发方式,上图中的4个SubPlan共有3种不同的PlanDistribution方式</p>        <ul>         <li> <p>Source :表示这个SubPlan是数据源,Source类型的任务会按照数据源大小确定分配多少个节点进行执行</p> </li>         <li> <p>Fixed:   表示这个SubPlan会分配固定的节点数进行执行(Config配置中的query.initial-hash-partitions参数配置,默认是8)</p> </li>         <li> <p>None:   表示这个SubPlan只分配到一个节点进行执行</p> </li>        </ul> </li>       <li> <p>OutputPartitioning:表示这个SubPlan的输出是否按照partitionBy的key值对数据进行Shuffle <em>(洗牌)</em> , 只有两个值 HASH和NONE</p> </li>      </ol> </li>    </ul>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/1d1c3d620942a9faa284573803a2f23c.png"></p>    <ul>     <li> <p>在上图的执行计划中,SubPlan1和SubPlan0 PlanDistribution=Source,这两个SubPlan都是提供数据源的节点,SubPlan1所有节点的读取数据都会发向SubPlan0的每一个节点;SubPlan2分配8个节点执行最终的聚合操作;SubPlan3只负责输出最后计算完成的数据,如下图:</p> </li>    </ul>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/5790d040ae026e0cdfbeaa2f5a1396bd.png"></p>    <ul>     <li> <p>SubPlan1和SubPlan0  作为Source节点,它们读取HDFS文件数据的方式就是调用的HDFS InputSplit API,然后每个InputSplit分配一个Worker节点去执行,每个Worker节点分配的InputSplit数目上限是参数可配置的,Config中的query.max-pending-splits-per-node参数配置,默认是100</p> </li>     <li> <p>SubPlan1的每个节点读取一个Split的数据并过滤后将数据分发给每个SubPlan0节点进行Join操作和Partial Aggr操作</p> </li>     <li> <p>SubPlan0的每个节点计算完成后按GroupBy Key的Hash值将数据分发到不同的SubPlan2节点</p> </li>     <li> <p>所有SubPlan2节点计算完成后将数据分发到SubPlan3节点</p> </li>     <li> <p>SubPlan3节点计算完成后通知Coordinator结束查询,并将数据发送给Coordinator</p> </li>    </ul>    <p><strong>presto引擎对比</strong></p>    <ul>     <li> <p>与hive、SparkSQL对比结果图</p> </li>    </ul>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/a50c2c63a5f5f0d176fb47e11077df8d.png"></p>    <p> </p>    <p>来自:http://www.cnblogs.com/tgzhu/p/6033373.html</p>    <p> </p>