道のHadoopは、(3)地図 - シャッフル削減の詳細とソースコード解析を学びます

@ [TOC]
ここに画像を挿入説明

ステージ1の分割

     MapReduceのマップタスクの最初、受信したファイル入力HDF、ファイルの先頭に指定されたサイズの複数の部分に切断される前に、各部分が分割と呼ばれ、デフォルトのブロックサイズは、分割の大きさに等しい、128メガバイトであります。スプリットに、minSizeのサイズ、maxSizeの、例としてWORDCOUNTコードのブロックサイズの決定は、以下の(主である)方法
ここに画像を挿入説明
waitForCompletion(true)方法は、進行submit()方法が
ここに画像を挿入説明
見つけreturn submitter .submitJobInternal(Job.this, cluster);
入る、検索int maps = writeSplits(job, submitJobDir);
ここに画像を挿入説明
ここに画像を挿入説明
writeNewSplits()方法は
ここに画像を挿入説明
     writeNewSplits()メソッドに入り、この方法は、第一の情報アレイ分割を求めることがわかります、並べ替え、優先順位は、大きなファイルを扱うことになります。最終リターンマッパーの数。それが2つの部分に分かれて:スライスとスライス書き込まれた情報の数を決定します。完了したタスクの数がgetSplits(ジョブ)のFileInputFormatスライスをいう決定、タスクライトにスライス情報はJobSplitWriter.createSplitFilesをいう(jobSubmitDir、CONF、jobSubmitDir.getFileSystem( CONF)、アレイ) 情報とSplitMetaInfoをスライスするメソッド、彼らはHDFSに書かれているreturn array.length;マップ、マップがデフォルトの番号であることをタスクの数のリターン:default_num = total_size / block_size;
     ターン内のスライスの数は、入力フォーマットによって決定されるマッパーの実際の数は、スライスの番号を入力することで、デフォルトはTextInputFormatあり、クラスはFileInputFormatのサブクラスです。タスクの数を決定しgetSplits(ジョブ)のFileInputFormatスライスが完了した言及しました。抽象クラスのInputFormat FileInputFormatから継承、MapReduceのクラスは、入力されたジョブの仕様を定義する、前記抽象メソッド一覧<InputSplit> getSplits(JobContextコンテキスト)を定義する方法分割入力InputSplit、異なる入力が異なる論理パーティションを有し、仕切りメソッドの戻り値はマッパーの数を決定するように、それぞれ異なるInputSplitは、マッパープロセスを得るいいます。

ステージ2地図

     每个map task都有一个内存缓冲区, map的输出结果先写到内存中的环形缓冲区,缓冲区为100M,不断的向缓冲区力写数据,当达到80M时,需要将缓冲区中的数据以一个临时文件的方式存到磁盘,当整个map task结束后再对磁盘中这个map task所产生的所有临时文件做合并,生成最终的输出文件。最后,等待reduce task来拉取数据。当然,如果map task的结果不大,能够完全存储到内存缓冲区,且未达到内存缓冲区的阀值,那么就不会有写临时文件到磁盘的操作,也不会有后面的合并。在写入的过程中会进行分区、排序、combine操作。
     环形缓冲区:是使用指针机制把内存中的地址首尾相接形成一个存储中间数据的缓存区域,默认100MB;80M阈值,20M缓冲区,是为了解决写入环形缓冲区数据的速度大于写出到spill文件的速度是数据的不丢失;Spill文件:spill文件是环形缓冲区到达阈值后写入到磁盘的单个文件.这些文件在map阶段计算结束时,会合成分好区的一个merge文件供给给reduce任务抓取;spill文件过小的时候,就不会浪费io资源合并merge;默认情况下3个以下spill文件不合并;对于在环形缓冲区中的数据,最终达不到80m但是数据已经计算完毕的情况,map任务将会调用flush将缓冲区中的数据强行写出spill文件。

     经过map类处理后,输出到内存缓冲区(默认大小100M),超过一定大小后,文件溢写到磁盘上,按照key分类
ここに画像を挿入説明
按照key合并成大文件,减少网络开销
ここに画像を挿入説明

2.1分区

看一下MapReduce自带的分区器HashPartitioner
ここに画像を挿入説明
假设有听个reduce任务,则分区的计算如下:
ここに画像を挿入説明

2.2排序

在对map结果进行分区之后,对于落在相同的分区中的键值对,要进行排序。

3 Shuffle阶段

     Shuffle过程是MapReduce的核心,描述着数据从map task输出到reduce task输入的这段过程。reducetask根据自己的分区号,去各个maptask分区机器上取相应的结果分区数据,reducetask会将这些文件再进行合并(归并排序)。
     所有相同key的数据汇集到一个partition
ここに画像を挿入説明
     将相同的key value汇聚到一起, 但不计算
ここに画像を挿入説明

4 Reduce阶段

reduce阶段分三个步骤:
抓取,合并,排序
     1 reduce 任务会创建并行的抓取线程(fetcher)负责从完成的map任务中获取结果文件,是否完成是通过rpc心跳监听,通过http协议抓取;默认是5个抓取线程,可调,为了是整体并行,在map任务量大,分区多的时候,抓取线程调大;
     2 抓取过来的数据会先保存在内存中,如果内存过大也溢出,不可见,不可调,但是单位是每个merge文件,不会切分数据;每个merge文件都会被封装成一个segment的对象,这个对象控制着这个merge文件的读取记录操作,有两种情况出现:在内存中有merge数据 •在溢写之后存到磁盘上的数据 •通过构造函数的区分,来分别创建对应的segment对象
     3 这种segment对象会放到一个内存队列中MergerQueue,对内存和磁盘上的数据分别进行合并,内存中的merge对应的segment直接合并,磁盘中的合并与一个叫做合并因子的factor有关(默认是10)
     4 排序问题,MergerQueue继承轮换排序的接口,每一个segment 是排好序的,而且按照key的值大小逻辑(和真的大小没关系);每一个segment的第一个key都是逻辑最小,而所有的segment的排序是按照第一个key大小排序的,最小的在前面,这种逻辑总能保证第一个segment的第一个key值是所有key的逻辑最小文件合并之后,最终交给reduce函数计算的,是MergeQueue队列,每次计算的提取数据逻辑都是提取第一个segment的第一个key和value数据,一旦segment被调用了提取key的方法,MergeQueue队列将会整体重新按照最小key对segment排序,最终形成整体有序的计算结果;
ここに画像を挿入説明
ここに画像を挿入説明
パーティション数を減らし、出力ファイルと同じ
ここに画像を挿入説明
数のタスクを減らす
だけ一組のタスクを減らした場合、大量のデータの場合には、他のノードが下効率が配置大きな値(最大:72)を減らすように、アイドル状態になり。ノードの数を調整する作業方法の数を減らし、複数の要因によってマップとしてではないタスクの数のタスクを減らし

通过参数调节mapred.reduce.tasks(在配置文件中)
在代码中调用job.setNumReduceTasks(int n)方法(在code中)

おすすめ

転載: blog.51cto.com/10312890/2461264