在編寫MapReduce程序時,經常會遇到這樣的問題,全局變量如何保存?如何讓每個處理都能獲取保存的這些全局變量?使用全局變量是不可避免的,但是 在MapRdeuce中直接使用代碼級別的全局變量是不現實的。主要是因為繼承Mapper基類的Map階段類的運行和繼承Reducer基類的 Reduce階段類的運行都是獨立的,並不共享一個Java虛擬機的資源,因此,下面介紹三種在MapReduce編程中相對有效的設置全局共享數據的方 法。
1,讀寫HDFS文件
在MapReduce框架中,Map Task和Reduce Task都運行在Hadoop集群的節點上,所以Map和Reduce Task、甚至不同的Job都可以通過讀寫HDFS中預定好的同一文件來實現全局共享數據。具體實現是利用Hadoop 的Java API來完成,需要注意的是,多個Map或Reduce的寫操作會產生沖突,覆蓋原有數據。
這種方法的優點是能夠實現讀寫,也比較直觀,但是缺點是需要共享一些很小的全局數據也需要使用IO,這將占用系統資源,增加作業完成的資源消耗。
2,配置Job屬性
在MapReduce執行過程中,task可以讀取Job的屬性。基於這個特性,我們可以在任務啟動之初利用Configuration類中的 set(String name,String value)將一些簡單的全局數據封裝到作業的配置屬性中,然后task再利用Configuration中的get(String name)獲取配置到屬性中的全局數據。
這種方法的優點是簡單,資源消耗小,但是對量比較大的共享數據顯得比較無力。(個人推薦這種)
3,使用DistributedCache
DistributedCache是MapReduce為應用提供緩存文件的只讀工具,它可以緩存文本文件,壓縮文件和jar文件等。在使用時,用戶可以 在作業配置中使用本地或HDFS文件的URL來將其設置成共享緩存文件。在作業啟動之后和task啟動之前,MapReduce框架會將可能需要的緩存文 件復制到執行任務節點的本地。
這種方法的優點是每個Job共享文件只會子啊啟動之后復制一次,並且它適用與大量的共享數據,而缺點是它是只讀的。
下面是一個簡單的使用DistributedCache的例子。
1)將要緩存的文件復制到HDFS上
1
|
bin/hadoop fs -copyFromLocal lookup /myapp/lookup
|
2)啟動作業的屬性配置,並設置待緩存文件
1
2
|
Configuration conf =
new
Configuration();
DistributedCache.addCacheFile(
new
URL(
"/myapp/lookup #lookup"
),conf);
|
3)在Map函數中使用DistributedCache
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
public
static
class
Map
extends
Mapper<Object, Text, Text,Text>{
private
Path[] localArchives;
private
Pah[] localFiles;
public
void
setup(Context context)
throws
IOException,InterruptedException{
//獲取緩存文件
Configuration conf =
new
Configuration();
localArchives = DistributedCache.getLocalCacheArchives(conf);
localFiles = DistributedCache.getLocalCacheFiles(conf);
}
public
void
map(K key, V value, Context context)
throws
IOException{
//使用緩存文件中獲取的數據
...
Context.collect(k,v);
}
}
|