MapReduce: Job提交過程

[i]初學Hadoop,準備用幾篇日誌來陳述MapReduce job的生命週期中job提交、task分發和task執行,以及JT scheduling策略,job性能參考等方面的知識。通過代碼及參考資料想了解job執行的大致細節,期望在以後job性能調優時有所依據。與細節相關的代碼參考於Hadoop-0.21.0版本。[/i]
[size=medium]
MapReduce依賴Hadoop FileSystem存儲job執行過程中需要的所有資源文件。這些文件有job的jar文件、job的配置文件、job的mapper需要處理的目標文件(輸入文件)以及job的輸出結果。MapReduce可以根據配置文件中File System的URI判斷當前是使用哪種Hadoop支持的File System,默認是local system。我更關注job在TT上的表現,而TT又是依賴於DN,所以之後所說的File System都是指HDFS。

運行在Cluster上的MapReduce job需要關注的配置文件有:mapred-default.xml與mapred-site.xml,它們之間沒有太大的區別,從名稱上分,site文件中應當配置與Cluster有關的內容,default就可以隨便配置了。與它們有關的引文有:[url=http://wiki.apache.org/hadoop/HowToConfigure]How To Configure[/url] 和 [url=http://hadoop.apache.org/common/docs/current/cluster_setup.html]Cluster setup[/url]。[/size]

[img]http://farm3.static.flickr.com/2627/3944125521_854eb00024.jpg[/img]

[size=medium]
上圖表示job的完整執行流程。本篇blog只關注從第一步到第四步的具體實現,當然也會從模擬的例子按步就班敘述。下面開始我們的進程。。。

MapReduce自帶WordCount的例子,如流程第一步,在設置基本的參數後,啓動job[/size]

Cluster cluster = new Cluster(config);
Job job = Job.getInstance(cluster);

job.setMapperClass(WordMapper.class);
job.setReducerClass(WordReducer.class);
job.setJarByClass(WordCount.class);
job.setCombinerClass(WordReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);

FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));

job.submit();


[size=medium]
注意這裏的FileInputFormat.addInputPath(job, path),首先得確定MapReduce的輸入文件或目錄應該在File system上存在,如果MapReduce依賴於HDFS,就得先將本地的文件上傳到HDFS上。MapReduce爲了防止一個job的輸出結果覆蓋之前job的輸出結果,要求每個job的輸出目錄都必須獨立與其它job,且這個目錄在job初始化時不應該存在,只有job需要時纔去創建,否則就會報錯。我以爲MapReduce會在用戶第一次設置輸出目錄時去檢查這個目錄的有效性,但事實上它是等做了一大堆事情後纔去檢查,這點讓我很困惑。

在job提交初期,也如流程中的第二步,client會向JT申請一個jobID來作爲job的標識符。jobID的格式如[color=darkred]job_201101281410_0001[/color],中間的字符串爲JT的標識符,後面是job的序號,從1開始一直遞增。

在得到jobID後,MapReduce就需要將job執行必要的資源文件copy到File system上去。在copy之前,我們得先確定這些資源文件存放在File system的什麼地方。JT設置有一個工作目錄(Staging area, 也稱數據中轉站),用來存儲與每個job相關的數據。這個目錄的前綴由mapreduce.jobtracker.staging.root.dir 參數來指定,默認是/tmp/hadoop/mapred/staging,每個client user可以提交多個job,在這個目錄後就得附加user name的信息。所以這個工作目錄(Staging area)類似於:/tmp/hadoop/mapred/staging/denny/.staging/。與job相關的資源文件存儲的目錄是工作目錄+jobID:${Staging area}/job_201101281410_0001。

這些資源文件存儲的情況如下:[/size]
 
stagingArea/job_yyyyMMddHHmm_tttt/job.jar 執行job任務的那個jar文件
stagingArea/job_yyyyMMddHHmm_tttt/files 存儲job的輸入文件
stagingArea/job_yyyyMMddHHmm_tttt/libjars 與job相關的其它jar文件
stagingArea/job_yyyyMMddHHmm_tttt/archives job的archives文件


[size=medium] 如果當前的File system是HDFS,那麼對於上面的每個文件,我們會設置它在HDFS的replication,這個值由mapreduce.client.submit.file.replication參數指定,默認是10,比普通HDFS文件的默認幅本數大很多,可能也是考慮到把輸入數據放到更多的DT上,儘可能實現本地數據計算。

把資源文件上傳到File system之後,負責job提交的程序會檢查job設置的輸出目錄(output dir)。如果這個目錄沒有指定或是目錄在File system上存在,就會拋出異常。爲啥非要在上傳那麼多文件後才做這項關鍵檢查呢?

接下來纔是整個job提交過程中最重要的一步:對輸入文件做數據分片(input split)。MapReduce過程中每個mapper怎樣知道處理輸入文件的哪部分內容呢?理應在mapper執行之前就確定它處理數據的範圍吧,那現在的數據分片工作就是幹這種事的。更主要的是分片的數量決定map task的數量,它們之間一一對應。這種數據分片(split)只是邏輯分片,記錄它應當訪問哪個block,及在這個block上的起始index及數據長度的信息。

下面我們細說怎樣劃分數據分片。job可能會有多個輸入文件,或許分佈在不同的目錄下。我們獲取輸入目錄的設置,然後識別得到我們需要處理的那些文件。這裏我們可以設置一個PathFilter來過濾那些目錄中的文件是否符合我們的要求,自定義的PathFilter類可由mapreduce.input.pathFilter.class屬性來設置。對於我們獲取的每一個輸入文件,根據它的block信息產生數據分片,文件之間不能產生分片。我們可以設置數據分片的數據大小,最小字節數由mapreduce.input.fileinputformat.split.minsize設置,默認是1,最大字節數由mapreduce.input.fileinputformat.split.maxsize設置,默認是Long.MAX_VALUE。由用戶定義的分片大小的設置及每個文件block大小的設置,可以計算得分片的大小。計算分片大小的公式是[/size]
splitSize = Math.max(minSize, Math.min(maxSize, blockSize))

[size=medium]從公式可以看出,如果maxSize設置大於blockSize,那麼每個block就是一個分片,否則就會將一個block文件分隔爲多個分片,如果block中剩下的一小段數據量小於splitSize,還是認爲它是獨立的分片。

產生分片後我們要把這些數據保存起來,序列化到stagingArea/job_yyyyMMddHHmm_tttt/job.split文件中,之後在map task運行時纔可以訪問到。同時爲每個分片分成一個MetaData信息,這個MetaData信息包含每個分片是放在哪臺slave server上,它是由JT訪問,且作爲有效分發map task到擁有物理文件的那臺slave server的依據。MetaData信息保存於stagingArea/job_yyyyMMddHHmm_tttt/job.splitmetainfo文件中。

至此,job提交所需要準備的數據大都已經就緒,前面一步的分片任務也確定了需要多少個map task,與job相關的配置都已確定。把job的配置文件上傳到stagingArea/job_yyyyMMddHHmm_tttt/job.xml文件中,在client端做的任務就完成了。Client嘗試與JT通信,然後把job提交到JT。

提交到JT後的工作與job初始化的細節,下一節再說。

[/size]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章