來源:http://www.ashishpaliwal.com/blog/2012/04/using-hadoop-distributed-cache/
Hadoop has a distributed cache mechanism to make available file locally that may be needed by Map/Reduce jobs. This post tried to expand a bit more on the information provided by the javadoc of DistributedCache
Use Case
Lets understand our Use Case a bit more in details so that we can follow-up the code snippets.
We have a Key-Value file that we need to use in our Map jobs. For simplicity, lets say we need to replace all keywords that we encounter during parsing, with some other value.
So what we need is
- A key-values files (Lets use a Properties files)
- The Mapper code that uses the code
Step 1
Place the key-values file on the HDFS
1.
hadoop
fs -put ./keyvalues.properties cache/keyvalues.properties
This path is relative to the user's home folder on HDFS
Step 2
Write the Mapper code that uses it
01.
public
class
DistributedCacheMapper
extends
Mapper<LongWritable,
Text, Text, Text> {
02.
03.
Properties
cache;
04.
05.
@Override
06.
protected
void
setup(Context
context)
throws
IOException,
InterruptedException {
07.
super
.setup(context);
08.
Path[]
localCacheFiles = DistributedCache.getLocalCacheFiles(context.getConfiguration());
09.
10.
if
(localCacheFiles
!=
null
)
{
11.
//
expecting only single file here
12.
for
(
int
i
=
0
;
i < localCacheFiles.length; i++) {
13.
Path
localCacheFile = localCacheFiles[i];
14.
cache
=
new
Properties();
15.
cache.load(
new
FileReader(localCacheFile.toString()));
16.
}
17.
}
else
{
18.
//
do your error handling here
19.
}
20.
21.
}
22.
23.
@Override
24.
public
void
map(LongWritable
key, Text value, Context context)
throws
IOException,
InterruptedException {
25.
//
use the cache here
26.
//
if value contains some attribute, cache.get(<value>)
27.
//
do some action or replace with something else
28.
}
29.
30.
}
Mapper code is simple enough. During the setup phase, we read the file and populate the Properties object. And inside the map() we use the cache to lookup for certain keys and replace them, if they are present.
Step 3
Add the properties file to your driver code
1.
JobConf
jobConf =
new
JobConf();
2.
//
set job properties
3.
//
set the cache file
4.
DistributedCache.addCacheFile(
new
URI(
"cache/keyvalues.properties#keyvalues.properties"
),
jobConf);
一些資料:
DistributedCache
DistributedCache 可將具體應用相關的、大尺寸的、只讀的文件有效地分佈放置。
DistributedCache 是Map/Reduce框架提供的功能,能夠緩存應用程序所需的文件 (包括文本,檔案文件,jar文件等)。
應用程序在JobConf中通過url(hdfs://)指定需要被緩存的文件。 DistributedCache假定由hdfs://格式url指定的文件已經在 FileSystem上了。
Map-Redcue框架在作業所有任務執行之前會把必要的文件拷貝到slave節點上。 它運行高效是因爲每個作業的文件只拷貝一次並且爲那些沒有文檔的slave節點緩存文檔。
DistributedCache 根據緩存文檔修改的時間戳進行追蹤。 在作業執行期間,當前應用程序或者外部程序不能修改緩存文件。
distributedCache可以分發簡單的只讀數據或文本文件,也可以分發複雜類型的文件例如歸檔文件和jar文件。歸檔文件(zip,tar,tgz和tar.gz文件)在slave節點上會被解檔(un-archived)。 這些文件可以設置執行權限。
用戶可以通過設置mapred.cache.{files|archives}來分發文件。 如果要分發多個文件,可以使用逗號分隔文件所在路徑。也可以利用API來設置該屬性: DistributedCache.addCacheFile(URI,conf)/DistributedCache.addCacheArchive(URI,conf) and DistributedCache.setCacheFiles(URIs,conf)/ DistributedCache.setCacheArchives(URIs,conf) 其中URI的形式是 hdfs://host:port/absolute-path#link-name 在Streaming程序中,可以通過命令行選項 -cacheFile/-cacheArchive 分發文件。
用戶可以通過 DistributedCache.createSymlink(Configuration)方法讓DistributedCache 在當前工作目錄下創建到緩存文件的符號鏈接。 或者通過設置配置文件屬性mapred.create.symlink爲yes。 分佈式緩存會截取URI的片段作爲鏈接的名字。 例如,URI是 hdfs://namenode:port/lib.so.1#lib.so, 則在task當前工作目錄會有名爲lib.so的鏈接, 它會鏈接分佈式緩存中的lib.so.1。
DistributedCache可在map/reduce任務中作爲 一種基礎軟件分發機制使用。它可以被用於分發jar包和本地庫(native libraries)。 DistributedCache.addArchiveToClassPath(Path, Configuration)和DistributedCache.addFileToClassPath(Path, Configuration) API能夠被用於 緩存文件和jar包,並把它們加入子jvm的classpath。也可以通過設置配置文檔裏的屬性 mapred.job.classpath.{files|archives}達到相同的效果。緩存文件可用於分發和裝載本地庫。