传统的MapReduce框架慢在那里
为什么之前的MapReduce系统比较慢
常理上有几个理由使得MapReduce框架慢于MPP数据库:
- 容错所引入的昂贵数据实体化
(data materialization)开销。 - 孱弱的数据布局
(data layout),比如缺少索引。 - 执行策略的开销[1 2]。
而我们对于Hive的实验也进一步证明了上述的理由,但是通过对Hive“工程上”的改进,如改变存储引擎(内存存储引擎)、改善执行架构(partial DAG execution)能够缩小此种差距。同时我们也发现一些MapReduce实现的细节会对性能有巨大的影响,如任务调度的开销,如果减小调度开销将极大地提高负载的均衡性。
中间结果输出:类似于Hive这样的基于MapReduce的查询引擎,往往会将中间结果实体化(materialize)到磁盘上:
- 在MapReduce任务内部,为了防止Reduce任务的失败,Map通常会把结果存储在磁盘上。
- 通常一些查询在翻译到MapReduce任务的时候,往往会产生多个stage,而这些串联的stage则又依赖于底层文件系统(如HDFS)来存储每一个stage的输出结果。
对于第一种情况,Map的输出结果存储在磁盘上是为了确保能够有足够的空间来存储这些大数据批量任务的输出。而Map的输出并不会复制到不同的节点上去,因此如果执行Map任务的节点失效的话仍会造成数据丢失[3]。由此可以推出,如果将这部分输出数据缓存在内存中,而不是全部输出到磁盘上面也是合理的。Shark Shuffle的实现正是应用了此推论,将Map的输出结果存储在内存中,极大地提高Shuffle的吞吐量。通常对于聚合(aggregation)和过滤之类的查询,它们的输出结果往往远小于输入,这种设计是非常合理的。而SSD的流行,也会极大地提高随机读取的性能,对于大数据量的Shuffle,能够获得较大的吞吐量,同时也拥有比内存更大的空间。
对于第二种情况,一些执行引擎扩展了MapReduce的执行模型,将MapReduce的执行模型泛化成更为通用的执行计划图(task DAG),可以将多stage的任务串联执行而无需将stage中间结果输出到HDFS中去,这些引擎包括Dryad[4], Tenzing[5]和Spark[6]。
数据格式和布局(layout): 由于MapReduce单纯的Schema-on-read的处理方式会引起较大的处理开销,许多系统在MapReduce模型内部设计和使用了更高效的存储结构来加速查询。Hive本身支持“分区表(table partitions)”(一种基本的类索引系统,它将特定的键段存储在特定的文件中,可以避免对于整个表的扫描),类似于磁盘数据的列式存储结构[7]。在Shark中我们更进一步地采用了基于内存的列式存储结构,Shark在实现此结构时并没有修改Spark的代码,而是简单地将一组列式元组存储为Spark内的一条记录,而对于列式元组内的结构则有Shark负责解析。
另一个Spark独有的特性是能够控制数据在不同节点上的分区,这为Shark带来了一种新的功能:对表进行联合分区(co-partition)。
最后,对于RDD我们还未挖掘其随机读取的能力,虽然对于写入操作,RDD只能支持粗粒度的操作,但对于读取操作,RDD可以精确到每一条记录[6],这使得RDD可以用来作为索引, Tenzing 可以用此来作为join操作的远程查询表(remote-lookup)。
执行策略: Hive在数据Shuffle之前花费了大量的时间用来排序,同时将MapReduce结果输出到HDFS上面也占用了大量的时间,这些都是由于Hadoop自身基本的,单次迭代的MapReduce模型所限制的。对于Spark这样的更通用的执行引擎,则可减轻上述问题带来的开销。举例来说,Spark支持基于Hash的分布式聚合和更为通用任务执行计划图(DAG)。
事实上,为了能够真正优化关系型查询的执行,我们发现在基于数据统计的基础上来选择执行计划是非常有必要的。但是由于UDF和复杂分析函数的存在,而Shark又将其视为一等公民(first-class citizens),这种统计将变得十分困难。为了能够解决这个问题,我们提出了partial DAG execution (PDE),这使得Spark能够在基于数据统计的基础上改变后续执行计划图,PDE与其他系统(DryadLINQ)的运行时执行计划图重写的不同在于:它能够收集键值范围内的细粒度统计数据;能够完全重新选择join的执行策略,如broadcast join,而不仅仅是选择Reduce任务的个数。
任务调度的开销: 大概在诸多影响Shark的部分中,最令人感到意外的却只是一个纯粹工程上的问题:运行任务带来的开销。传统的MapReduce系统,就比如Hadoop,是为了运行长达数小时的批量作业而设计的,而组成作业的每个任务其运行时间则有数分钟之久,他们会在独立的系统进程中执行任务,在某些极端情况下提交一个任务的延迟非常之高。拿Hadoop打比方,它使用周期性的“心跳”消息来向工作节点分配任务,而这个周期是3秒钟,因此总共的任务启动延时就会高达5-10秒。这对于批处理的系统显然是可以忍受的,但是对于实时查询这显然是不够的。
为了避免上述问题,Spark采用了事件驱动的RPC类库来启动任务,通过复用工作进程来避免系统进程开销。它能够在一秒钟内启动上千个任务,任务之间的延时小于5毫秒,从而使得50-100毫秒的任务,500毫秒的作业变得可能。而这种改进对于查询性能的提升,甚至对于较长执行时间的查询性能的提升也令我们感到吃惊不已。
亚秒级的任务使得引擎能够更好地在工作节点之间平衡任务的分配,甚至在某些节点遇到了不可预知的延迟(网络延迟或是JVM垃圾回收)的情况下面也能较好地平衡。同时对于数据倾斜也有巨大的帮助,考虑到在100个核上做哈希聚合(hash aggregation),对于每一个任务所处理的键范围需要精心选定,任何的数据倾斜的部分都会拖慢整个作业。但是如果将作业分发到1000个核上面,那么最慢的任务只会比平均任务慢10倍,这就大大提高了可接受程度。而当我们在PDE中应用倾斜感知的选择策略后,令我们感到失望的是相比于增大Reduce任务个数带来的提升,这种策略所带来的提升却比较小。但不可否认的是,引擎对于异常数据倾斜有了更高的稳定性。
在Hadoop/Hive中,错误的选择任务数量往往会比优化好的执行策略慢上10倍,因此有大量的工作集中在如何自动的选择Reduce任务的数量[8 9],下图可以看到Hadoop/Hive和Spark Reduce任务数量对于作业执行时间的影响。因为Spark作业能够以较小的开销运行数千个Reduce任务,数据倾斜的影响可以通过运行较多任务来减小。
事实上,对于更大规模集群(数万个节点)上亚秒级任务的可行性我们还未探究。但是对于Dremel[10]这样的周期性地在数千个节点上运行亚秒级作业的系统,实际情况下当单个主节点无法满足任务调度的速度时,调度策略可以将任务委派给子集群的“副”主节点。同时细粒度的任务执行策略相比于粗粒度的设计不仅仅带来了负载均衡的好处,而且还包括快速恢复(fast recovery)(通过将失败任务分发到更多的节点上去)、查询的弹性(query elasticity)。
细粒度任务模型(Fine-Grained Task Modle)带来的其他好处
虽然这篇文章主要关注的是细粒度任务模型带来的容错性优势,这个模型同样也提供了许多诱人的特性,接下将会介绍在MapReduce系统中已被证明的两个特性。
伸缩性(Elasticity): 在传统的MPP数据库中,一旦分布式执行计划被选中,系统就必须以此并行度执行整一个的查询。但是在细粒度任务系统中,在执行查询的过程中节点可以增删节点,系统会自动地把阻塞的作业分发到其他节点上去,这使得整个系统变得非常具有伸缩性。如果数据库管理者需要在这个系统中移除某些节点,系统可以简单地将这些节点视为失效节点,或者更好的处理方法是将这些节点上的数据复制到其他节点上去。与删除节点相对应的是,当执行查询变得更慢时,数据库系统可以动态地申请更多的资源来提升计算能力。亚马逊的Elastic MapReduce[11]已经支持运行时调整集群规模。
多租户架构(Multitenancy): 多租户架构如同上面提到伸缩性一样,目的是为了在不同用户之间动态地共享资源。在传统的MPP数据库中,当一个重要的查询提交的时候已经有一个较大的查询占据了大多数的集群资源,这时能做的选择不外乎就是取消先前的查询等有限的操作。而在基于细粒度任务模型的系统中,查询作业可以等待几秒到当前作业完成,然后提交新的查询作业。Facebook和Microsoft已经为Hadoop和Dryad开发了公平调度器,使得大型的、计算密集型的历史记录查询与实时的小型查询可以共享集群资源而不会产生饥饿现象[12 13]。
传统的MapReduce框架慢在那里的更多相关文章
- Hadoop 之 MapReduce 框架演变详解
经典版的MapReduce 所谓的经典版本的MapReduce框架,也是Hadoop第一版成熟的商用框架,简单易用是它的特点,来看一幅图架构图: 上面的这幅图我们暂且可以称谓Hadoop的V1.0版本 ...
- Hadoop 新 MapReduce 框架 Yarn 详解
Hadoop 新 MapReduce 框架 Yarn 详解: http://www.ibm.com/developerworks/cn/opensource/os-cn-hadoop-yarn/ Ap ...
- mapreduce框架详解
hadoop 学习笔记:mapreduce框架详解 开始聊mapreduce,mapreduce是hadoop的计算框架,我学hadoop是从hive开始入手,再到hdfs,当我学习hdfs时候,就感 ...
- Hadoop 新 MapReduce 框架 Yarn 详解【转】
[转自:http://www.ibm.com/developerworks/cn/opensource/os-cn-hadoop-yarn/] 简介: 本文介绍了 Hadoop 自 0.23.0 版本 ...
- Hadoop mapreduce框架简介
传统hadoop MapReduce架构(老架构) 从上图中可以清楚的看出原 MapReduce 程序的流程及设计思路: 1.首先用户程序 (JobClient) 提交了一个 job,job ...
- hadoop 学习笔记:mapreduce框架详解
开始聊mapreduce,mapreduce是hadoop的计算框架,我学hadoop是从hive开始入手,再到hdfs,当我学习hdfs时候,就感觉到hdfs和mapreduce关系的紧密.这个可能 ...
- Hadoop学习笔记:MapReduce框架详解
开始聊mapreduce,mapreduce是hadoop的计算框架,我学hadoop是从hive开始入手,再到hdfs,当我学习hdfs时候,就感觉到hdfs和mapreduce关系的紧密.这个可能 ...
- 更快、更强——解析Hadoop新一代MapReduce框架Yarn(CSDN)
摘要:本文介绍了Hadoop 自0.23.0版本后新的MapReduce框架(Yarn)原理.优势.运作机制和配置方法等:着重介绍新的Yarn框架相对于原框架的差异及改进. 编者按:对于业界的大数据存 ...
- 提升资源利用率的MapReduce框架
Hadoop系统提供了MapReduce计算框架的开源实现,像Yahoo!.Facebook.淘宝.中移动.百度.腾讯等公司都在借助 Hadoop进行海量数据处理.Hadoop系统性能不仅取决于任务调 ...
随机推荐
- Redis安装与测试
①安装,直接安装版本为4.0.1 sudo apt-get install redis-server 启动: redis-server redis-cli 测试: ②新建Student表 ③查看zha ...
- [CISCO] 思科交换机基本配置
思科交换机基本配置 交换机是局域网中最重要的设备,交换机是基于 MAC 来进行工作的.和路由器类似,交换 机也有 IOS,IOS 的基本使用方法是一样的.本章将简单介绍交换机的一些基本配置,以及交换 ...
- 永久激活navicat_premium12.0,支持win32和64位
1.下载软件以及注册机 链接:https://pan.baidu.com/s/1NGc6YLsgMQRQYEwnGSU16Q 提取码:guno 2.根据自己的电脑位数安装对应的软件,傻瓜式安全(注 ...
- Centos7下安装CUDA
https://developer.nvidia.com/cuda-80-ga2-download-archive https://developer.nvidia.com/rdp/cudnn-dow ...
- 【性能测试】脚本开发,最普通的http协议脚本
放上来做个备份: Action() { double transTime; // 事务消耗时间 lr_start_transaction("营销_01_MSMH0011_查询拥有码列表&qu ...
- Handover
In brief, eNodeB select one MME based on IE: Relative MME Capacity in S1 Setup Response, S-GW and P- ...
- springmvc执行原理及自定义mvc框架
springmvc是spring的一部分,也是一个优秀的mvc框架,其执行原理如下: (1)浏览器提交请求经web容器(比如tomcat)转发到中央调度器dispatcherServlet. (2)中 ...
- WCF系列教程之客户端异步调用服务
本文参考自http://www.cnblogs.com/wangweimutou/p/4409227.html,纯属读书笔记,加深记忆 一.简介 在前面的随笔中,详细的介绍了WCF客户端服务的调用方法 ...
- 【文档】二、Binlog结构和内容概述
binlog是一系列文件,这些文件包含了Mysql服务实例中数据的变化. binlog包含一系列二进制日志文件,还包含一个索引文件. 每个日志文件包含了一个4字节的魔法数,后面跟着描述数据变化的事件内 ...
- javascript中的function 函数名(){} 和 函数名:function(){}有什么不同
function functionName(){};这是定义一个函数 functionName:function(){};是设置一个对象的方法. 下面举一个例子: <html> <h ...