Map Reduce - noonecare/opensourcebigdatatools GitHub Wiki

hadoop 的出现是为了解决如何高效地处理海量数据的问题。为此效率问题,没有办法回避。

简单想, Map Reduce 模式把任务分配给多个节点(host) 去做。这样如果一个任务之前需要30 天去完成,有 30 个节点,任务完全是可以分解的(只有 map 任务)而且可以均分,那么hadoop 就只需要 1 天就可以完成。这样我们知道数据必然会在集群上传输,也必然会有任务的分配和监督。下面更进一步,分析 hadoop 是如何完成这些工作的。

hadoop 性能的瓶颈所在

  • 数据量大,从 HDFS 各个节点之间传递数据势必会耗时。
  • 中间处理结果保存在硬盘上,也需要在节点之间传输。
  • 并行度 map 数,也必然会决定处理的速度。
  • map/reduce 之间有 shuffle/sort 的操作。
  • shuffle 导致的数据分配不均衡。一个处理 1 亿条数据,分成了 100 个任务, 有 99 个 task 都只包含 10 条记录,有一个 task 包含了将近 1 亿条数据,这样,job 的性能卡在那个要处理将近 1 亿条数据的 task, 和没有分配任务之前,性能上不会有多大的提高。
  • reduce 像一种极端情况,只有一个 reduce, 那么如果数据量大 reduce 过程很可能成为瓶颈。
  • 集群上不仅仅运行一个 job, 多个 job 之间的调度也必然影响一个 job 的效率。
  • 硬件(程序解决不了,但确实有影响)。

hadoop 的解决办法

  • 数据传输:
  • 为了提高效率,应当尽量就地处理数据(data locality)。避免数据在集群的不同的 node 之间传输。 Hadoop 在分配任务(一个任务(job)会被分成多个 task 去做,每个 task 会在一个节点上运行)时,会查询 HDFS 的数据拓扑结构(就是数据都分布在那些节点,block 都在那些节点),根据数据的拓扑结构,按照尽可能就地处理数据(data locality)的方针,分配任务。简而言之,map 阶段 Hadoop 默认就会尽量就地处理数据。我们不必做什么操作。但如果是 shuffle 阶段,我们可以做操作。shuffle 时(比如 A shuffle B),hadoop 会保留 A 的分区,把 B 的数据传到 A 数据所在的节点,进行操作。这样, B 数据一定会在 集群各个节点之间传输。所以如果 A, B 要做 shuffle, 一般都数据量大的数据放在 shuffle 操作的左边(作为第一个操作数)。比如在 hive/impala 上, 表要做 join, 大表应该位于左边。
  • 中间结果也可能会在集群各个节点之间传输, 这样,为了减小传输的量, 对于一些运算(比如记录是句子,任务是要得出所有句子中最长句子的字数,那么 map 的结果是每个句子的长度,reduce 得出句子的最大值)。 可以对于每个 map 结果在本地做一次运算减小中间结果的大小(对于map结果,统计最大值,把这个最大值传输给 reducer, 这样一个数字,比如一堆数字(每句话都有个长度,所以是一堆数字)小)
  • 压缩,数据压缩之后再传输。这样做需要注意两点:
  • 压缩解压缩,是要占用 CPU 时间的,如果压缩解压缩耗时长的话,是不能提高效率的。不过一般压缩总体上还是能提高效率的。
  • 如果压缩格式不是 splitable 的,hadoop 不会把一个压缩文件,分成多个 map task 执行。
  • map 数

  • inputsplit, task, splitable

  • HDFS 上的文件是以多个 block 的形式保存的,如果数据没有压缩,或者压缩格式是 splitable 的(比如 bz2), 那么每个 block 的数据会成为一个 inputsplit, 这个 inputsplit 会分配成一个 task, 交由一个 node 去执行(当然如果执行中出错,会再交给其他节点处理)。
  • 如果数据被压缩,而且压缩格式不是 splitable 的(比如 gzip), 整个数据会分配成一个 inputsplit, 分配成一个 task, 交由一个 node 去执行。
  • 调整 map 数
  • 和 spark 不一样,没有现成的 API 去调整,就是根据数据本身的大小去分配的。
  • 不要保存过多的小文件。文件太小, 在每个节点上执行 task 的 overhead 的执行时间占的比重会升高,浪费时间。
  • reduce 数
  • 任务失败和监督
  • 每个 task 是可能失败的。比如你一个 task 去读 100G 的数据到内存,必然会失败。那么都要哪些因素可能导致任务的失败:

配置 Job:

Process

  • InputFormat(read input)
  • Map
  • combine
  • Partition
  • Shuffle
  • sort
  • reduce
  • OutputFormat(write output)

mapper number versus reduce number

Common Ways to Improve Performance