其實MapReduce作業運行第三方配置文件的共享方法往小了說其實就是參數在MapReduce作業中的傳遞,往大了說其實就是DistributedCache的應用。
在MapReduce中傳遞參數普遍用Configuration,Configuration是一個鍵值對,將所需的參數值表示成鍵值對(鍵值對爲字符串類型),調用Configuration的set方法就保存進去了,用的時候調用get方法。
這是最基礎的,在工作中難免遇到一些特殊的情況,比如,如何傳遞一個對象型參數?當你的MapReduce作業依賴第三方jar包,而這個第三方jar包又需要從集羣本地讀取一些配置文件,這種情況又改怎麼把配置文件傳給集羣中的各個節點呢?
對象類型的參數可以覆蓋這個對象的toString()方法,將它的所有元素表示成字符串,然後使用Configuration.set(name, value)傳遞這個字符串,然後用的時候get到這個字符串,做析構。這種方法容易造成精度上的丟失,並且容易帶來空間上的浪費。比如double類型轉換成字符串,不僅精度有損失,而且8字節的空間用字符串來表示可能會變成幾十字節。其次不靈活,如果修改了這個對象的結構可能會有bug哦。
另一種比較nice的方法是利用Hadoop的api中的DefaultStringifier,此類有兩個方法store和load,分別用來設置和獲取。用法爲
DefaultStringifier.store(conf, obj ,"keyname");
將object以序列化後以指定的key存在conf中。
object = DefaultStringifier.load(conf, "keyname", variableClass );
其中conf爲MapReduce作業當前的配置環境conf,obj爲傳入的對象,keyname爲此obj在conf中的標識,variableclass爲obj獲取後轉化成的class類,
此方法需要注意一點是obj這個對象需要實現Writable接口,使它具有序列化的能力。此對象的Writable接口可以自己實現也可以將此obj轉化爲BytesWritable類型的,這樣在從conf中取出的時候還得進行反轉,轉化方法可以這樣寫
private static BytesWritable transfer( Object patterns ) { ByteArrayOutputStream baos = null; ObjectOutputStream oos = null; try { baos = new ByteArrayOutputStream( ); oos = new ObjectOutputStream( baos ); oos.writeObject( patterns ); oos.flush( ); return new BytesWritable( baos.toByteArray( ) ); } catch( Exception e ) { logger.error( "", e ); } finally { IoUtils.close( baos ); IoUtils.close( oos ); } return null; }
反轉方法爲
private static Object transferMRC( byte[] bytes ) { // MapWritable map = new MapWritable( ); ObjectInputStream is = null; try { is = new ObjectInputStream( new ByteArrayInputStream( bytes ) ); return is.readObject( ); } catch( Exception e ) { logger.error( "", e ); } finally { IoUtils.close( is ); } return null; }但是如果遇到更大的參數呢?比如分詞用的語料庫等等,這時就應該用到Hadoop的緩存機制DistributedCache了。
DistributedCache是hadoop框架提供的一種機制,可以將job指定的文件,在job執行前,先行分發到task執行的機器上,並有相關機制對cache文件進行管理。具體用法隨後介紹,隨後會有一篇專門介紹DistributedCache的文章。