靠谱 的软件外包伙伴

您的位置:首页 > 新闻动态 > 百度分布式搜索查询平台软件开发架构演进!

百度分布式搜索查询平台软件开发架构演进!

2016-03-25 10:56:02

PINGO是一个由百度大数据部与百度美国研发中心合作而成的分布式交换查询平台。在PINGO之前,百度的大数据查询作业主要由基于Hive的百度QueryEngine去完成。QueryEngine很好的支持着百度的离线计算任务,可是它对交互式的在线计算任务支持并不好。为了更好的支持交互式任务,我们在大约一年前设计了基于SparkSQL与Tachyon的PINGO的雏形。在过去一年中, 通过跟不同业务的结合,PINGO逐渐的演变成一套成熟高效的交互式查询系统。本文将详细介绍PINGO的架构迭代过程以及性能评估。

PINGO设计目标

QueryEngine是基于Hive的百度内部的大数据查询平台,这套系统在过去几年中较好的支撑了百度的相关业务。 图1展示了QueryEngine的架构图,其服务入口叫做Magi。用户向Magi提交查询请求, Magi为这次请求分配一个执行机, 执行机会调用Hive读取Meta信息并向Hadoop队列提交任务. 在这一过程中, 用户需要自行提供计算需要的队列资源。随着近几年对大数据平台的要求越来越高, 我们在使用QueryEngine过程中也发现了一些问题:首先QueryEngine需要由用户提供计算资源, 这使得数据仓库的用户需要去了解Hadoop以及相关的管理流程, 这增加了用户使用数据的门槛。 第二, 对于很多小型计算任务而言, MR的任务的起动时间也较长, 往往用户的计算任务只需要1分钟, 但是排队/提交任务就需要超过一分钟甚至更长的时间。这样的结果是,QueryEngine虽然很好的支持线下执行时间长的任务,但是对线上的一些交换式查询任务(要求延时在一到两分钟内)确是无能为力。

图片描述

图1: Query Engine 的执行流程

 

为了解决这些问题, 在大约一年前,我们尝试在离线计算的技术栈上搭建起一套具有在线服务属性的SQL计算服务 PINGO。如图2所示: PINGO使用了SparkSQL为主要的执行引擎, 主要是因为Spark具有下面的特点:

  • 内存计算:Spark以RDD形式把许多数据存放在内存中,尽量减少落盘,从而提升了计算性能。
  • 可常驻服务:Spark可以帮助实现常驻式的计算服务, 而传统的Hadoop做不到这一点。常驻式的计算服务有助于降低数据查询服务的响应延迟。
  • 机器学习支持:对于数据仓库的使用, 不应仅仅局限于SQL类的统计任务。 Spark的机器学习库可以帮助我们将来扩展数据仓库, 提供的交互式的数据挖掘功能。
  • 计算功能多元:虽然PINGO是一个查询服务, 不过仍然有其他类型的计算需求, 如数据预处理等。 使用Spark可以使我们用一个计算引擎完成所有的任务, 简化系统的设计。

图片描述

图2: PINGO初版系统架构设计

 

PINGO系统迭代

在过去一年中,PINGO从一个雏形开始,通过跟不同业务的结合,逐渐的演变成一套成熟高效的系统。中间经历过几次的架构演变,在本章中,我们将详细介绍PINGO的迭代过程。

PINGO 1.0

PINGO初版的目标是提升性能,让其能支持交互式查询的任务。由于Spark是基于内存的计算引擎,相对于Hive有一定的性能优势, 所以第一步我们选择使用Spark SQL。为求简单,最初的服务是搭建在Spark Standalone集群上的。我们知道, Spark在Standalone模式下是不支持资源伸缩的, 一个Spark Application在启动的时候会根据配置获取计算资源。 这时就算一个查询请求只有一个Task还在运行, 该Application所占用的所有资源都不能释放。好在一个Spark Application可以同时运行多个Job, 每个Job都能够’平分’其所占用的计算资源。

图片描述

图3: PINGO 1.0 系统架构

 

基于上面的考虑, 如图3所示,我们利用Spark的Standalone集群搭建了第一版PINGO服务. 我们的主服务节点叫做Operation Manager, 它本身也是一个Spark Driver。所有用户的请求都会从Magi Service发送到Magi Worker, 再由Magi Worker分配给Operation Manager, 通过Operation Manager在Spark集群上执行。

PINGO 1.1

通过PINGO 1.0, 我们把数据仓库的计算引擎从Hive/MR转变成了Spark。 不过, 单纯的替换计算引擎, 也许可以把查询的性能提升1-2倍, 但是并不会使查询的速度有数量级上的提高. 想要从本质上提高查询速度, 我们还需要改进存储。对此我们设计了PINGO 1.1, 加入了以Tachyon为载体的缓存系统,并在缓存层上搭建了缓存管理系统ViewManager, 进一步提升系统性能。

很多快速的查询系统都将Parquet之类列存储格式和分布式KeyValue存储引擎结合起来, 通过建立索引/物化视图等手段加速SQL查询的速度. 通过将部分查询条件下推到存储引擎, 某些SQL查询语句甚至可以被提速至100倍以上。然而我们的数据都存储在旧版本的Hive数据仓库中, 文件系统被限定为HDFS, 数据格式一般为低版本的ORC File, 也有不少表是ORCFile或者文本。 因为迁移成本/数据上下游依赖等兼容性等原因, 我们没有办法更改Hive数据仓库本身的存储.

不过根据局部性原理, 任何数据访问都有热点. 我们可以建立缓存系统, 在缓存系统中应用最新的文件系统和存储格式. 通过把热点输入通过预加载的方式导入到缓存系统, 我们可以加速整个系统的访问性能.为此, 我们设计了以下的系统架构:

图片描述

图4: PINGO 1.1 系统架构

 

在这个架构中, 我们引入了一个新模块 ViewManager, 该模块负责管理缓存系统。 它的主要功能是识别热点数据, 将数据导入到缓存系统中, 并在查询时改变SQL的执行过程, 使得Spark从缓存而不是原始位置读取数据。在这个架构下,当一个Query进来时,会先向OperationManager请求。当接受到请求后,OperationManager会向ViewManager查询数据是否已经在缓存中。如果已经在缓存,数据将被直接返回给用户, Query完成。如果数据不在缓存中,OperationManager会向底层Data Warehouse发起请求, 等数据到达时返回給用户。同时,ViewManager也会向底层Data Warehouse发起请求, 等数据到达时建立一个Cache Entry, 这样的话下次同样Query进来时,就会从缓存读数据。注意这里我们OperationManager与ViewManager对会向底层Data Warehouse的数据读取是两个独立的STREAM, 这样保证两者不会互相干扰。

那PINGO又是如何动态去读取缓存中或者底层Data Warehouse的数据的呢?毕竟在Query Plan中,数据地址是写死的。 为了能够让缓存对用户透明, 我们在SparkSQL上做了一些改进, 如下图所述

图片描述

图5: PINGO1.1 对SparkSQL的改进

 

Spark中利用Catalyst框架来执行SQL语句。 对于Catalyst框架来说, 其输入是Unresolved Logical Plan, 这可以简单理解为SQL语句的结构化描述。 Catalyst调用Catalog来向MetaService查询表的