Hadoop MapReduce性能优化

影响MapReduce输入数据处理时间的因素很多。其中之一是实现map和reduce函数时使用的算法。其他外部因素也可能影响MapReduce性能。根据我们的经验和观察,可能影响MapReduce的主要因素有以下几个。

  • 硬件(或者资源)因素,如CPU时钟、磁盘I/O、网络带宽和内存大小。
  • 底层存储系统。
  • 输入数据、分拣(shuffle)数据以及输出数据的大小,这与作业的运行时间紧密相关。
  • 作业算法(或者程序),如map、reduce、partition、combine和compress。有些算法很难在MapReduce中概念化,或者在MapReduce中效率可能会降低。

运行map任务时,shuffle子任务的中间输出存储在内存缓冲区中,用以减少磁盘I/O。输出的大小可能会超过内存缓冲区而造成溢出,因此需要spill子阶段把数据刷新到本地文件系统。这个子阶段也会影响MapReduce性能,它经常采用多线程技术实现,以便使磁盘I/O利用率最大化并缩减作业的运行时间。

MapReduce编程模型允许用户使用自己的map和reduce函数指定数据转换逻辑。本模型并不限定map函数产生的中间对在交由reduce函数处理前如何被分组。因此,归并排序(merge-sort)算法被用作默认的分类算法。然而,归并排序算法并非总是最高效的,尤其是对分析型任务(如聚合和等值连接)而言,这类任务并不关心中间键的顺序。

提示.tif对于MapReduce编程模型来说,分组(grouping)/划分(partitioning)是一个串行的任务。这就意味着在reduce任务可以运行之前,框架需要等待所有map任务完成。

想要深入学习归并排序算法,请参考​​http://en.wikipedia.org/wiki/Merge_sort​​。

MapReduce性能是以map和reduce的运行时间为基础的。这是因为典型环境下集群节点数目和节点插槽数目这类参数是不可修改的。

其他可能对MapReduce性能构成潜在影响的因素具体如下。

  • I/O模式:也就是从存储系统获取数据的方式。从底层存储系统读取数据有以下两种模式。
    直接I/O:通过硬件控制器把数据从本地硬盘缓存中直接读到内存,因而不需要进程间通信成本。

流式I/O:通过特定进程间通信手段,如TCP/IP和JDBC,从其他正在运行进程(典型情况是存储系统进程)读取数据。

从提高性能的角度看,使用直接I/O比流式I/O更高效。

  • 输入数据解析:是指从存储系统获取数据时,从原始数据到键值对的转换过程。数据解析过程的目标是把原始数据按照原来的格式解码,并转换为可供Java等编程语言处理的数据对象。

输入数据可以解码为(Java或者其他语言)对象,这样当对象实例创建后,对象内容可以改变,典型的情况是使用对对象实例的引用(这样的对象叫做可变对象),输入数据也可以解码为一经创建其内容就不可改变的对象(叫做不可变对象)。在上百万条记录的情况下,不可变对象的解码过程会明显比可变对象的解码过程慢,这是因为在前者解码过程中产生了大量不可变对象。因此,这会导致系统性能的降低。 - 输入数据存储:当MapReduce获取数据并进行进一步处理时,所在的存储系统必须保证高速访问和数据可用性(如HDFS和HBase)。如果选用的不是那些推荐的与MapReduce一起使用的存储文件系统,那么输入数据的访问会潜在地影响MapReduce性能。

使用Hadoop框架时,许多因素可能会影响整个系统的性能和作业的运行时间。这些因素可能是Hadoop MapReduce引擎的一部分,也可能是引擎之外的。

Hadoop配置参数通常会影响并发运行的任务数,并决定作业的运行时间,因为Hadoop集群被建立且作业开始执行后,其他因素就不可改变了。如果Hadoop框架配置不当,可能无法充分利用集群资源,并因此影响MapReduce作业性能。这是因为大量的配置参数控制着Hadoop框架的行为。

一项Hadoop作业经常由许多实现不同算法的子模块组成,这些子模块要么以串行方式连接,要么以并行方式连接。如果Hadoop框架配置不当,可能会影响内部任务完成的协作方式。所有这类参数(将在第2章讨论)设置的影响都依赖于map和reduce函数的代码、集群资源,当然还有输入数据。

MapReduce作业的性能也可能受Hadoop集群节点数的影响,以及受所有节点中运行map和reduce任务的可用资源的影响。每个节点的容量决定了一个节点可以执行的mapper和recducer任务的数量。因此,如果节点资源利用不充分或者过度利用,都会直接影响MapReduce任务的性能。