Yarn(MapReduce 2.0)下分散式快取(DistributedCache)的注意事項
1、問題
最近公司的叢集從 Apache hadoop 0.20.203 升級到了 CDH 4,邁進了 Hadoop 2.0 的新時代,雖然新一代的 hadoop 努力做了架構、API 上的各種相容, 但總有“照顧不周”的地方,下面說的這個有關分散式快取的案例就是於此有關:一些 MR job 遷移到 Yarn 上後,發覺沒資料了,而且沒有報錯。 查了下資料來源和程式碼,發現是分散式快取(DistributedCache)的用法有點小變化。以前的老程式碼大致如下:
(1)在 main 函式中新增分散式快取檔案:
... String cacheFilePath = "/dsap/rawdata/cmc_unitparameter/20140308/part-m-00000"; DistributedCache.addCacheFile(new Path(cacheFilePath).toUri(), job.getConfiguration()); ...
(2)在 MR 初始化的時候讀取快取檔案做資料字典:
...
// 從當前作業中獲取要快取的檔案
Path[] paths = DistributedCache.getLocalCacheFiles(context.getConfiguration());
for (Path path : paths) {
if (path.toString().contains("cmc_unitparameter")) {
...
(3)結果:
這兩段程式碼在 MR1 時代毫無問題,但是到了 MR2 時代 if 是永遠為 false 的。 特意對比了下 MR1 和 MR2 時代的 path 格式,可以看到在 MRv2 下,Path 中不包含原始路徑資訊了:
MR1 Path: hdfs://host:fs_port/dsap/rawdata/cmc_unitparameter/20140308/part-m-00000 MR1 Path: hdfs://host:fs_port/dsap/rawdata/cmc_unitparameter/20140308/part-m-00000 MR2 Path: /data4/yarn/local/usercache/root/appcache/application_1394073762364_1884/container_1394073762364_1884_01_000006/part-m-00000 MR2 Path: /data17/yarn/local/usercache/root/appcache/application_1394073762364_1884/container_1394073762364_1884_01_000002/part-m-00000 MR2 Path: /data23/yarn/local/usercache/root/appcache/application_1394073762364_1884/container_1394073762364_1884_01_000005/part-m-00000
看了上面兩種差異我想你能明白為啥分散式快取在 MR2 下面“失效了”。。。
2、解決方案
解決這個問題不難:
其實在 MR1 時代我們上面的程式碼是不夠規範的,每次都遍歷了整個分散式快取,我們應該用到一個小技巧:createSymlink
(1)main 函式中為每個快取檔案新增符號連結:類似於 HTTP URL 的 # 錨點一樣
...
String cacheFilePath = "/dsap/rawdata/cmc_unitparameter/20140308/part-m-00000";
Path inPath = new Path(cacheFilePath);
// # 號之後的名稱是對上面檔案的連結,不同檔案的連結名不能相同,雖然由你自己隨便取
String inPathLink=inPath.toUri().toString()+"#"+"DIYFileName";
DistributedCache.addCacheFile(new URI(inPathLink), job.getConfiguration());
...
加了軟連結後,path 資訊的最後部分就是你剛才的 DIYFileName:
/data4/yarn/local/usercache/root/appcache/application_1394073762364_1966/container_1394073762364_1966_01_000005/cmcs_paracontrolvalues
/data4/yarn/local/usercache/root/appcache/application_1394073762364_1966/container_1394073762364_1966_01_000005/cmc_unitparameter
(2)在需要用快取檔案的地方直接根據你剛才 # 後面自定義的檔名讀取即可
BufferedReader br = null;
br = new BufferedReader(new InputStreamReader(new FileInputStream("DIYFileName")));
(3)其它地方的用法和程式碼與 MR1 無任何變化。
3、Refer:
1、Hadoop 多表 join:map side join 範例
http://my.oschina.net/leejun2005/blog/111963
2、Hadoop DistributedCache詳解
http://dongxicheng.org/mapreduce-nextgen/hadoop-distributedcache-details/
3、迭代式MapReduce解決方案(二) DistributedCache
http://hongweiyi.com/2012/02/iterative-mapred-distcache/
4、DistributedCache小記