递交job流程

一个MR任务会递交一个 job,MR任务包括 MapTask 和 ReduceTask 任务。
会在 jobid 命名的目录下递交3个文件:切片信息文件,MR的配置信息,待执行程序的jar

默认的InputFormat和RecordReader

hadoop 默认的 InputFormat 是 TextInputFormat,TextInputFormat方法默认返回一个 LineRecordReader。

环形缓冲区

每个 map task 会启动一个环形缓冲区

  1. 默认的环形缓冲区大小为100M,对一个 map task,默认的切片大小为128M。
  2. 当环形缓冲区达到80%时,即 80M时,会触发溢写,将在环形缓冲区中的80M数据分区内排序,然后溢写到磁盘文件中。(快排排索引,即环形缓冲区中 存储的元数据 的索引)
  3. 切片大小大于80M,所以一个map task可能会生成多个 溢写文件。
  4. 将多个 溢写文件 合并为一个大文件。此时会进行一次归并排序,继续保证文件分区内有序。
  5. 经过上述步骤,一个 map task 形成一个大文件。
  6. 多个map task 会形成多个大文件,这些大文件可以视情况使用 Combiner 进行一次合并(类似于 reduce task 做的归并排序)。

    几次排序及合并文件总结

    下面的文件均为分区内有序

  7. 每个 MapTask 由一个进程执行,每个 MapTask 任务会有一个对应的环形缓冲区,环形缓冲区可能会满多次,发多次溢写,因此会形成多个溢写文件,这些溢写文件会进行归并排序合并成一个大文件

  8. 多个MapTask生成的大文件进行一次归并排序形成一个大文件(可选流程)
  9. Reduce阶段会主动拉取每个 MapTask 形成的大文件某个分区的数据,进行一次归并排序。(会先尝试放在内存里,如果放的下,直接进行归并排序,从内存里直接传给 ReduceTask)。

一般一个分区的文件都比较大,内存放不下,会先一个一个拉到 Reduce 的磁盘中,然后再将拉到 Reducer 的文件进行归并排序 得到一个整体有序(单个分区的)的大文件,对这个大文件按 key 分组,将分好组的数 据传给Reducer。

分区总结

分区的个数核心由 ReduceTask 的个数决定。
(1)ReduceTask 的个数 > 分区数,则会产生几个空的输出文件,如 part-r-000xx
(2)ReduceTask 的个数为1,不管分区数为多少,最终只会输出一个文件,part-r-00000
(3)ReduceTask 的个数 < 分区数,一部分分区数据无处安放,会产生 Exception

Hadoop集群资源分配问题

集群有30台机器,跑mr任务的时候发现5个map任务全都分配到了同一台机器上,这个可能是由于什么原因导致的吗?
解决方案:yarn.scheduler.fair.assignmultiple这个参数 默认是开的,需要关掉。

该参数控制 是否允许NodeManager一次分配多个容器,开着,则可能在一台机器上同时开启多个容器,同时跑多个map任务。